summaryrefslogtreecommitdiff
path: root/src/util
diff options
context:
space:
mode:
authorday <day@national.shitposting.agency>2026-03-16 16:25:49 +0100
committerday <day@national.shitposting.agency>2026-03-16 16:25:49 +0100
commit7f85c9fc75bd62ac09ea4457d3b17f85988fca66 (patch)
tree15248e42bfafc6bd19e50c9010b701057958ff3a /src/util
parent872c39b24ecf4063f785ff3e8b2f940acd8c2d59 (diff)
parent991352b0d2767e6bd1a46f554db4ac9d208c13ad (diff)
Merge remote-tracking branch 'origin/master' into obj
Diffstat (limited to 'src/util')
-rw-r--r--src/util/allocator.h11
-rw-r--r--src/util/callback.h84
-rw-r--r--src/util/color.h4
-rw-r--r--src/util/config.h25
-rw-r--r--src/util/config/config.cpp13
-rw-r--r--src/util/config/serializers.cpp115
-rw-r--r--src/util/file.h4
-rw-r--r--src/util/input.h3
-rw-r--r--src/util/str_tokenizer.h140
-rw-r--r--src/util/string.h27
-rw-r--r--src/util/vector.h8
11 files changed, 335 insertions, 99 deletions
diff --git a/src/util/allocator.h b/src/util/allocator.h
index 327dfc1..623d227 100644
--- a/src/util/allocator.h
+++ b/src/util/allocator.h
@@ -2,8 +2,7 @@
#include <stdlib.h>
#include <string.h>
-#include <functional>
-#include "typedef.h"
+#include "callback.h"
template <typename T>
struct LIST_ITERATOR {
@@ -19,7 +18,7 @@ struct LIST_ITERATOR {
};
template <typename T>
-using QSORT_FN = std::function< U8( T*, T* ) >;
+using QSORT_FN = FN< U8( T*, T* ) >;
template <typename T>
static U8 qsort_basic_sort( T* t1, T* t2 ) {
@@ -58,8 +57,8 @@ struct LIST {
U32 capacity;
U32 size;
- using ON_EACH_FN = std::function< void(T*) >;
- using ON_SEARCH_FN = std::function< bool(T*) >;
+ using ON_EACH_FN = FN< void(T*) >;
+ using ON_SEARCH_FN = FN< U8(T*) >;
LIST() {
data = (T*)malloc( sizeof( T ) );
@@ -265,6 +264,8 @@ struct LIST {
}
T ret = data[--size];
+ if constexpr( !__is_trivially_destructible(T) )
+ data[size].~T();
if( size < capacity / 4 )
shrink();
diff --git a/src/util/callback.h b/src/util/callback.h
new file mode 100644
index 0000000..a2c9477
--- /dev/null
+++ b/src/util/callback.h
@@ -0,0 +1,84 @@
+#pragma once
+#include "typedef.h"
+
+template <typename T>
+struct FN;
+// voodoo
+template <typename RET, typename... ARGS>
+struct FN<RET(ARGS...)> {
+ template <typename T> struct __strip_ref { using type = T; };
+ template <typename T> struct __strip_ref<T&> { using type = T; };
+ template <typename T> struct __strip_ref<T&&> { using type = T; };
+ template <typename R, typename... A> struct __strip_ref<R(A...)> { using type = R(*)(A...); };
+ template <typename R, typename... A> struct __strip_ref<R(&)(A...)> { using type = R(*)(A...); };
+
+ static const unsigned int BUF_SIZE = 32;
+
+ alignas(8) char buf[BUF_SIZE];
+ void* data;
+ RET( *invoke )( void*, ARGS... );
+ void( *destroy )( void* );
+ void*( *clone )( void*, char* );
+
+ template <typename F>
+ FN(F&& f) {
+ using __stripped = typename __strip_ref<F>::type;
+
+ if constexpr( sizeof(__stripped) <= BUF_SIZE ) {
+ new (buf) __stripped( f );
+ data = buf;
+ destroy = pfn( void* d ) {
+ ( (__stripped*)d )->~__stripped();
+ };
+ clone = pfn( void* d, char* dst ) -> void* {
+ new (dst) __stripped( *(__stripped*)d );
+ return dst;
+ };
+ } else {
+ data = new __stripped( f );
+ destroy = pfn( void* d ) {
+ delete (__stripped*)d;
+ };
+ clone = pfn( void* d, char* dst ) -> void* {
+ return new __stripped( *(__stripped*)d );
+ };
+ }
+
+ invoke = pfn( void* d, ARGS... args ) -> RET {
+ return ( *(__stripped*)d )( args... );
+ };
+ }
+
+ FN( I32&& ) : data( 0 ), invoke( 0 ), destroy( 0 ), clone( 0 ) {}
+ FN( U32&& ) : data( 0 ), invoke( 0 ), destroy( 0 ), clone( 0 ) {}
+ FN() : data( 0 ), invoke( 0 ), destroy( 0 ), clone( 0 ) {}
+
+ FN( const FN& other ) : invoke( other.invoke ), destroy( other.destroy ), clone( other.clone ) {
+ if( !other.data ) {
+ data = 0;
+ return;
+ }
+
+ data = other.clone( other.data, buf );
+ }
+
+ FN& operator=( const FN& other ) {
+ if( this == &other ) return *this;
+ if( destroy && data ) destroy( data );
+ invoke = other.invoke;
+ destroy = other.destroy;
+ clone = other.clone;
+ data = other.data ? other.clone( other.data, buf ) : 0;
+ return *this;
+ }
+
+ ~FN() {
+ if( destroy && data ) destroy( data );
+ }
+
+ RET operator()( ARGS... args ) const {
+ return invoke( data, args... );
+ }
+
+ operator bool() const { return !!invoke; }
+};
diff --git a/src/util/color.h b/src/util/color.h
index 526cddc..8b1a259 100644
--- a/src/util/color.h
+++ b/src/util/color.h
@@ -1,5 +1,5 @@
#pragma once
-#include "typedef.h"
+#include "string.h"
#include <math.h>
struct CLR {
@@ -166,3 +166,5 @@ struct CLR {
return *this;
}
};
+
+inline STR to_str( CLR c ) { return STR( "%.02f %.02f %.02f %.02f", c.r, c.g, c.b, c.a ); }
diff --git a/src/util/config.h b/src/util/config.h
index 7973db0..d8c1c2e 100644
--- a/src/util/config.h
+++ b/src/util/config.h
@@ -1,7 +1,7 @@
#pragma once
#include <stdio.h>
-#include "allocator.h"
+#include "string.h"
#include "vector.h"
#include "color.h"
@@ -26,8 +26,8 @@ enum CfgNodeType_t {
// ===================================== [ definitions ] ===========================================
-using CFG_PARSEFN = std::function<void( CFG_PARSER*, CFG_SECTION*, char* )>;
-using CFG_SERIALIZEFN = std::function<void( CFG_SERIALIZER*, CFG_NODE*, char* )>;
+using CFG_PARSEFN = FN<STAT( CFG_PARSER*, CFG_SECTION*, char* )>;
+using CFG_SERIALIZEFN = FN<STR( CFG_SERIALIZER*, CFG_NODE*)>;
struct CFG_TYPE {
U8 type;
@@ -37,7 +37,7 @@ struct CFG_TYPE {
};
struct CFG_NODE {
- char name[64];
+ STR name;
CFG_NODE* parent;
U8 type;
};
@@ -66,14 +66,14 @@ extern STAT cfg_parser_clr( CFG_PARSER* parser, CFG_SECTION* section, char* name
// ====================================== [ serializers ] ==========================================
-extern void cfg_serialize_section( CFG_SERIALIZER* serializer, CFG_NODE* section, char* buf );
-extern void cfg_serialize_bytes( CFG_SERIALIZER* serializer, CFG_NODE* node, char* buf );
-extern void cfg_serialize_str( CFG_SERIALIZER* serializer, CFG_NODE* node, char* buf );
-extern void cfg_serialize_float( CFG_SERIALIZER* serializer, CFG_NODE* node, char* buf );
-extern void cfg_serialize_int( CFG_SERIALIZER* serializer, CFG_NODE* node, char* buf );
-extern void cfg_serialize_vec2( CFG_SERIALIZER* serializer, CFG_NODE* node, char* buf );
-extern void cfg_serialize_vec3( CFG_SERIALIZER* serializer, CFG_NODE* node, char* buf );
-extern void cfg_serialize_clr( CFG_SERIALIZER* serializer, CFG_NODE* node, char* buf );
+extern STR cfg_serialize_section( CFG_SERIALIZER* serializer, CFG_NODE* section );
+extern STR cfg_serialize_bytes( CFG_SERIALIZER* serializer, CFG_NODE* node );
+extern STR cfg_serialize_str( CFG_SERIALIZER* serializer, CFG_NODE* node );
+extern STR cfg_serialize_float( CFG_SERIALIZER* serializer, CFG_NODE* node );
+extern STR cfg_serialize_int( CFG_SERIALIZER* serializer, CFG_NODE* node );
+extern STR cfg_serialize_vec2( CFG_SERIALIZER* serializer, CFG_NODE* node );
+extern STR cfg_serialize_vec3( CFG_SERIALIZER* serializer, CFG_NODE* node );
+extern STR cfg_serialize_clr( CFG_SERIALIZER* serializer, CFG_NODE* node );
// ========================================= [ config ] ============================================
@@ -158,6 +158,7 @@ static void cfg_free( CFG_NODE* n ) {
else if( n->type == CFGT_SECTION ) {
CFG_SECTION* s = (CFG_SECTION*)n;
s->children.each( fn( CFG_NODE** child ) { cfg_free( *child ); } );
+ return delete s;
}
delete n;
diff --git a/src/util/config/config.cpp b/src/util/config/config.cpp
index a41e455..00a2512 100644
--- a/src/util/config/config.cpp
+++ b/src/util/config/config.cpp
@@ -30,9 +30,7 @@ inline void trim_whitespace( char* buf ) {
}
inline void init_cfg_node( CFG_NODE* node, const char* name, CFG_NODE* parent, U8 type ) {
- memset( node->name, 0, sizeof(node->name) );
- strcpy( node->name, name );
- node->name[sizeof(node->name) - 1] = '\0';
+ node->name = name;
node->parent = parent;
if( parent )
( (CFG_SECTION*)parent )->children.push( node );
@@ -290,17 +288,12 @@ STAT cfg_save( CFG_SECTION* root, const char* path ) {
if( !f )
return STAT_ERR;
- char* buf = (char*)malloc( 999999 );
- buf[0] = 0;
CFG_SERIALIZER s;
s.tabc = 0;
s.f = f;
- cfg_serialize_section( &s, (CFG_NODE*)root, buf );
- U32 len = strlen( buf );
-
- fwrite( buf, 1, len, f );
- free( buf );
+ STR buf = cfg_serialize_section( &s, (CFG_NODE*)root );
+ fwrite( buf, 1, buf.size, f );
fclose( f );
return STAT_OK;
diff --git a/src/util/config/serializers.cpp b/src/util/config/serializers.cpp
index 01f416c..15ddae0 100644
--- a/src/util/config/serializers.cpp
+++ b/src/util/config/serializers.cpp
@@ -1,109 +1,122 @@
-#include <cstdarg>
-#include <cstdio>
-
#include "../config.h"
-void serialize_node( CFG_SERIALIZER* s, CFG_NODE* n, char* buf ) {
- U32 len = strlen( buf );
- for( U32 i = 0; i < s->tabc * 2; ++i ) buf[i + len] = ' ';
- buf[len + s->tabc * 2] = 0;
- sprintf( buf, "%s%s %s", buf, cfg_types[n->type].def, n->name );
+STR serialize_node( CFG_SERIALIZER* s, CFG_NODE* n ) {
+ STR ret{};
+ for( U32 i = 0; i < s->tabc * 2; ++i ) ret.append( " " );
+ ret.fmt( "%s %s", cfg_types[n->type].def, n->name.data );
+
+ return ret;
}
-void cfg_serialize_section( CFG_SERIALIZER* s, CFG_NODE *n, char *buf ) {
+STR cfg_serialize_section( CFG_SERIALIZER* s, CFG_NODE *n ) {
CFG_SECTION* sec = (CFG_SECTION*)n;
+ STR buf;
if( sec->parent ) {
- serialize_node( s, n, buf );
- strcat( buf, " {\n" );
+ buf += serialize_node( s, n );
+ buf += " {\n";
s->tabc++;
}
- char line[8192];
for( U32 i = 0; i < sec->children.size; ++i ) {
- line[0] = 0;
CFG_NODE* c = sec->children[i];
if( c->type == CFGT_SECTION ) {
- cfg_serialize_section( s, c, buf );
+ buf += cfg_serialize_section( s, c );
continue;
}
- cfg_types[c->type].serializer( s, c, line );
- strcat( buf, line );
- strcat( buf, "\n" );
+ buf += cfg_types[c->type].serializer( s, c );
+ buf += "\n";
}
if( sec->parent ) {
s->tabc--;
- char tabbuf[512] = { 0 };
- for( U32 i = 0 ; i < s->tabc * 2; ++i )
- tabbuf[i] = ' ';
- tabbuf[s->tabc * 2] = 0;
- strcat( buf, tabbuf );
- strcat( buf, "}" );
+ for( U32 i = 0 ; i < s->tabc * 2; ++i ) buf += ' ';
+ buf += "}";
if( sec->parent )
- strcat( buf, "\n" );
+ buf += "\n";
}
+
+ return buf;
}
-void cfg_serialize_bytes( CFG_SERIALIZER* s, CFG_NODE* n, char* buf ) {
+STR cfg_serialize_bytes( CFG_SERIALIZER* s, CFG_NODE* n ) {
CFG_BYTES* b = (CFG_BYTES*)n;
U32 size = b->size;
U8* bytes = b->bytes;
- serialize_node( s, n, buf );
- sprintf( buf, "%s[%d] = \"", buf, size );
- U32 len = strlen( buf );
+ STR buf{};
+
+ buf += serialize_node( s, n );
+ buf.fmt( "[%d] = \"", size );
for( U32 i = 0; i < size; ++i ) {
- sprintf( buf + len + i * 2, "%02X", bytes[i] );
+ buf.fmt( "%02X", bytes[i] );
}
-
- sprintf( buf, "%s%s", buf, "\";" );
+ buf += "\";";
+ return buf;
}
-void cfg_serialize_str( CFG_SERIALIZER* s, CFG_NODE* n, char *buf ) {
+STR cfg_serialize_str( CFG_SERIALIZER* s, CFG_NODE* n ) {
CFG_STR* sn = (CFG_STR*)n;
char* str = sn->str;
- serialize_node( s, n, buf );
- sprintf( buf, "%s[%d] = \"%s\";", buf, sn->len, str );
+ STR buf{};
+
+ buf += serialize_node( s, n );
+ buf.fmt( "[%d] = \"%s\";", sn->len, str );
+ return buf;
}
-void cfg_serialize_int( CFG_SERIALIZER* s, CFG_NODE* n, char *buf ) {
- CFG_INT* i = (CFG_INT*)n;
- I32 ival = i->value;
+STR cfg_serialize_int( CFG_SERIALIZER* s, CFG_NODE* n ) {
+ CFG_INT* i = (CFG_INT*)n;
+ I32 ival = i->value;
- serialize_node( s, n, buf );
- sprintf( buf, "%s = %d;", buf, ival );
+ STR buf{};
+
+ buf += serialize_node( s, n );
+ buf.fmt( " = %d;", ival );
+ return buf;
}
-void cfg_serialize_float( CFG_SERIALIZER* s, CFG_NODE* n, char *buf ) {
+STR cfg_serialize_float( CFG_SERIALIZER* s, CFG_NODE* n ) {
CFG_FLOAT* f = (CFG_FLOAT*)n;
F32 fval = f->value;
- serialize_node( s, n, buf );
- sprintf( buf, "%s = %g;", buf, fval );
+ STR buf{};
+
+ buf += serialize_node( s, n );
+ buf.fmt( " = %g;", fval );
+ return buf;
}
-void cfg_serialize_vec2( CFG_SERIALIZER* s, CFG_NODE* n, char *buf ) {
+STR cfg_serialize_vec2( CFG_SERIALIZER* s, CFG_NODE* n ) {
CFG_VEC2* v = (CFG_VEC2*)n;
VEC2 val = v->value;
- serialize_node( s, n, buf );
- sprintf( buf, "%s = { %g, %g };", buf, val.x, val.y );
+ STR buf{};
+
+ buf += serialize_node( s, n );
+ buf.fmt( " = { %g, %g };", val.x, val.y );
+ return buf;
}
-void cfg_serialize_vec3( CFG_SERIALIZER* s, CFG_NODE* n, char *buf ) {
+STR cfg_serialize_vec3( CFG_SERIALIZER* s, CFG_NODE* n ) {
CFG_VEC3* v = (CFG_VEC3*)n;
VEC3 val = v->value;
- serialize_node( s, n, buf );
- sprintf( buf, "%s = { %g, %g, %g };", buf, val.x, val.y, val.z );
+ STR buf{};
+
+ buf += serialize_node( s, n );
+ buf.fmt( " = { %g, %g, %g };", val.x, val.y, val.z );
+ return buf;
}
-void cfg_serialize_clr( CFG_SERIALIZER* s, CFG_NODE* n, char *buf ) {
+STR cfg_serialize_clr( CFG_SERIALIZER* s, CFG_NODE* n ) {
CFG_CLR* v = (CFG_CLR*)n;
CLR val = v->value;
- serialize_node( s, n, buf );
- sprintf( buf, "%s = { %g, %g, %g, %g };", buf, val.r, val.g, val.b, val.a );
+ STR buf{};
+
+ buf += serialize_node( s, n );
+ buf.fmt( " = { %g, %g, %g, %g };", val.r, val.g, val.b, val.a );
+ return buf;
}
diff --git a/src/util/file.h b/src/util/file.h
index 7e4d413..4309e62 100644
--- a/src/util/file.h
+++ b/src/util/file.h
@@ -1,7 +1,7 @@
#pragma once
-#include <cstdlib>
-#include <cstring>
+#include <stdlib.h>
+#include <string.h>
#include <stdio.h>
#include <dirent.h>
#include <sys/stat.h>
diff --git a/src/util/input.h b/src/util/input.h
index 1317f94..af5e258 100644
--- a/src/util/input.h
+++ b/src/util/input.h
@@ -1,7 +1,6 @@
#pragma once
#include <SDL_events.h>
-#include <functional>
#include "vector.h"
#include "allocator.h"
@@ -33,7 +32,7 @@ struct INPUT_KEYBINDS {
U8 crouch = SDL_SCANCODE_LCTRL;
};
-using ON_INPUT_FN = std::function<void( SDL_Event* )>;
+using ON_INPUT_FN = FN<void( SDL_Event* )>;
struct INPUT_DATA {
MOUSE_DATA mouse;
diff --git a/src/util/str_tokenizer.h b/src/util/str_tokenizer.h
new file mode 100644
index 0000000..8a3aebf
--- /dev/null
+++ b/src/util/str_tokenizer.h
@@ -0,0 +1,140 @@
+#pragma once
+
+#include "string.h"
+
+using TOKENIZER_COMPARE_FN = FN<U8( char )>;
+
+struct STR_TOKENIZER {
+ STR str;
+ STR ignored;
+
+ I32 cur;
+ I32 last;
+};
+
+inline STR_TOKENIZER tok_init( STR str, STR whitespace_chars = " \t\n\r" ) {
+ return {
+ .str = str,
+ .ignored = { whitespace_chars },
+ .cur = 0,
+ .last = 0,
+ };
+}
+
+inline STR tok_next( STR_TOKENIZER* t ) {
+ if( t->cur >= t->str.size )
+ return "";
+
+ U8 start = 0;
+ for( I32 i = t->cur; i < t->str.size; i++ ) {
+ U8 c = t->str.data[i];
+ if( i == t->str.size - 1 ) {
+ if( !start )
+ return "";
+
+ STR ret = { (U32)i - t->cur + 1, t->str.data + t->cur };
+ t->last = t->cur;
+ t->cur = i + 1;
+ return ret;
+ }
+
+ for( auto& it : t->ignored ) {
+ if( c == it ) {
+ if( !start ) {
+ t->cur = i + 1;
+ continue;
+ } else {
+ STR ret = { (U32)i - t->cur, t->str.data + t->cur };
+ t->last = t->cur;
+ t->cur = i + 1;
+ return ret;
+ }
+ }
+ }
+
+ start = 1;
+ }
+
+ return "";
+}
+
+inline STR tok_peek( STR_TOKENIZER* t ) {
+ if( t->cur >= t->str.size )
+ return "";
+
+ U8 start = 0;
+ I32 cur = t->cur;
+ for( I32 i = cur; i < t->str.size; i++ ) {
+ U8 c = t->str.data[i];
+ if( i == t->str.size - 1 ) {
+ if( !start )
+ return "";
+
+ STR ret = { (U32)i - cur + 1, t->str.data + cur };
+ return ret;
+ }
+
+ for( auto& it : t->ignored ) {
+ if( c == it ) {
+ if( !start ) {
+ cur = i + 1;
+ continue;
+ } else {
+ STR ret = { (U32)i - cur, t->str.data + cur };
+ return ret;
+ }
+ }
+ }
+
+ start = 1;
+ }
+
+ return "";
+}
+
+
+inline STR tok_next( STR_TOKENIZER* t, STR what ) {
+ if( t->cur >= t->str.size )
+ return "";
+
+ if( !what.size )
+ return "";
+
+ for( I32 i = t->cur; i <= t->str.size - what.size; i++ ) {
+ STR slice = { what.size, t->str.data + i };
+ if( slice == what ) {
+ STR ret = { (U32)i - t->cur, t->str.data + i + what.size };
+ t->last = t->cur;
+ t->cur = i + what.size;
+ return ret;
+ }
+ }
+
+ return "";
+}
+
+inline char tok_nextchar( STR_TOKENIZER* t ) {
+ if( t->cur >= t->str.size )
+ return 0;
+
+ U32 last = t->cur;
+ for( ; t->cur < t->str.size; t->cur++ ) {
+ U8 cont = 0;
+ for( auto& it : t->ignored ) {
+ if( t->str.data[t->cur] == it ) {
+ cont = 1;
+ break;
+ }
+ }
+
+ if( cont )
+ continue;
+ else {
+ t->last = last;
+ t->cur++;
+ return t->str.data[t->cur];
+ }
+ }
+
+ return 0;
+}
diff --git a/src/util/string.h b/src/util/string.h
index 2268a36..672fb5d 100644
--- a/src/util/string.h
+++ b/src/util/string.h
@@ -55,8 +55,6 @@ template <typename CT>
struct __str : public LIST<CT> {
__str() : LIST<CT>() {}
__str( U32 count, const CT* str ) : LIST<CT>() {
- this->data = 0;
- this->capacity = 0;
this->reserve( count * 2 );
memcpy( this->data, str, count );
this->size = count;
@@ -69,8 +67,6 @@ struct __str : public LIST<CT> {
va_copy( args2, args );
U32 c = vsnprintf( 0, 0, fmt, args );
va_end( args );
- this->data = 0;
- this->capacity = 0;
this->reserve( c * 2 );
vsnprintf( this->data, c + 1, fmt, args2 );
this->data[c] = 0;
@@ -89,8 +85,6 @@ struct __str : public LIST<CT> {
if( this->data && this->data != other.data )
free( this->data );
- this->data = 0;
-
if( !other.capacity || !other.size ) {
this->capacity = 1;
this->size = 0;
@@ -116,8 +110,9 @@ struct __str : public LIST<CT> {
__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; }
+ __str<CT>& operator+=( const CT rhs ) { this->push( rhs ); return *this; }
+ operator const CT*() { return this->data; }
operator CT*() { return this->data; }
CT operator[]( U32 i ) {
@@ -128,10 +123,8 @@ struct __str : public LIST<CT> {
if( rhs.size != this->size )
return 0;
- for( U32 i = 0; i < this->size; ++i ) {
- if( this->data[i] != rhs.data[i] )
- return 0;
- }
+ if( !!memcmp( this->data, rhs.data, this->size ) )
+ return 0;
return 1;
}
@@ -165,7 +158,7 @@ struct __str : public LIST<CT> {
__str<CT>& append( const CT* str ) {
U32 len;
for( len = 0; !!str[len]; ++len );
- if( this->size + len > this->capacity )
+ if( this->size + len + 1 >= this->capacity )
this->reserve( this->size + len + 1 );
memcpy( this->data + this->size, str, len * sizeof(CT) );
@@ -179,7 +172,7 @@ struct __str : public LIST<CT> {
if( this->size + len + 1 >= this->capacity )
this->reserve( this->size + len + 1 );
- memcpy( this->data + this->size, str, len * sizeof(CT) );
+ memcpy( this->data + this->size, str.data, len * sizeof(CT) );
this->size += len;
this->data[this->size] = 0;
return *this;
@@ -281,3 +274,11 @@ struct __str : public LIST<CT> {
using STR = __str<char>;
using WSTR = __str<wchar_t>;
+
+inline STR to_str( F32 f ) { return STR( "%.02f", f ); }
+inline STR to_str( F64 f ) { return STR( "%.02g", f ); }
+inline STR to_str( I32 i ) { return STR( "%d", i ); }
+inline STR to_str( I64 i ) { return STR( "%lld", i ); }
+inline STR to_str( U32 u ) { return STR( "%u", u ); }
+inline STR to_str( U64 u ) { return STR( "%llu", u ); }
+inline STR to_str( void* p ) { return STR( "%llx", (U64)p ); }
diff --git a/src/util/vector.h b/src/util/vector.h
index 854b454..eb386ab 100644
--- a/src/util/vector.h
+++ b/src/util/vector.h
@@ -1,7 +1,7 @@
#pragma once
#include <math.h>
-#include "typedef.h"
+#include "string.h"
static const F32 PI = 3.14159265359f;
static const F32 PIRAD = 0.01745329251f;
@@ -13,7 +13,6 @@ struct VEC2 {
VEC2() { x = y = 0.0f; }
VEC2( F32 X, F32 Y ) { x = X; y = Y; }
- VEC2( const F32* v ) { x = v[0]; y = v[1]; }
VEC2( const VEC2& v ) { x = v.x; y = v.y; }
bool operator==( const VEC2& v ) const { return ( x == v.x && y == v.y ); }
@@ -49,7 +48,6 @@ struct VEC3 {
VEC3() { x = y = z = 0.0f; }
VEC3( F32 X, F32 Y, F32 Z ) { x = X; y = Y; z = Z; }
- VEC3( const F32* v ) { x = v[0]; y = v[1]; z = v[2]; }
VEC3( const VEC3& v ) { x = v.x; y = v.y; z = v.z; }
VEC3( const VEC2& v ) { x = v.x; y = v.y; z = 0.f; }
@@ -250,3 +248,7 @@ inline void angle_vectors( const VEC3& angles, VEC3* forward, VEC3* right, VEC3*
up->z = cr * cp;
}
}
+
+inline STR to_str( VEC2 v ) { return STR( "%.02f, %.02f", v.x, v.y ); }
+inline STR to_str( VEC3 v ) { return STR( "%.02f, %.02f, %.02f", v.x, v.y, v.z ); }
+inline STR to_str( VEC4 v ) { return STR( "%.02f, %.02f, %.02f, %.02f", v.x, v.y, v.z, v.w ); }