|
|
@ -7,20 +7,20 @@ |
|
|
|
#include "types.h" |
|
|
|
#include "alloc.h" |
|
|
|
|
|
|
|
#include <string.h> // @TODO remove this |
|
|
|
#include <cstring> // memcpy, memset, memcmp |
|
|
|
|
|
|
|
#define STB_SPRINTF_IMPLEMENTATION |
|
|
|
#define STB_SPRINTF_STATIC |
|
|
|
#include <stb/stb_sprintf.h> |
|
|
|
|
|
|
|
#define STR_MEMALLOC pMalloc |
|
|
|
#define STR_MEMFREE pFree |
|
|
|
#define STR_ASSERT assert |
|
|
|
#define STR_ASSERT assert |
|
|
|
#define STR_IMPLEMENTATION |
|
|
|
#define STR_SUPPORT_STD_STRING 0 |
|
|
|
#define STR_DEFINE_STR32 0 // the type Str32, which would normally be available, conflicts with a type in MacTypes.h |
|
|
|
|
|
|
|
|
|
|
|
static Allocator* _stringClassAllocator = &Allocator::GetDefault(); // only used for the string class, string functions you pass an allocator if it allocates |
|
|
|
|
|
|
|
// 'String' is a datatype, but it also is a namespace for a bunch of static 'char*' operations that |
|
|
|
// you would normally find in the <cstring> or <string.h> header |
|
|
|
// The datatype is a modified version of a string class developed by Omar Cornut: https://github.com/ocornut/str |
|
|
@ -99,7 +99,7 @@ public: |
|
|
|
return c == '0' || c == '1'; |
|
|
|
} |
|
|
|
|
|
|
|
static inline char* intToString(u64 integer) { |
|
|
|
static inline char* intToString(u64 integer) { // @ALLOC |
|
|
|
ULE_TYPES_H_FTAG; |
|
|
|
u32 capacity = 10; |
|
|
|
u32* remainders = (u32*) pMalloc(sizeof (u32) * capacity); |
|
|
@ -191,23 +191,24 @@ public: |
|
|
|
} |
|
|
|
|
|
|
|
// heap allocates a copy of |string| and returns a pointer to it. |
|
|
|
static inline char* cpy(const char* string, u32 length, Allocator* allocator = Allocator::GetDefault()) { |
|
|
|
static inline char* cpy(const char* string, u32 length, Allocator& allocator = Allocator::GetDefault()) { |
|
|
|
ULE_TYPES_H_FTAG; |
|
|
|
char* buffer = (char*) allocator->mallocate(sizeof (char) * (length + 1), allocator->state); |
|
|
|
assert(&allocator == &Allocator::GetDefault()); |
|
|
|
char* buffer = (char*) pMalloc(sizeof(char) * (length+1)); //allocator.mallocate(sizeof (char) * (length + 1), allocator.state); |
|
|
|
|
|
|
|
u32 i = 0; |
|
|
|
for (; i < length; i++) { |
|
|
|
buffer[i] = string[i]; |
|
|
|
} |
|
|
|
buffer[i] = '\0'; |
|
|
|
|
|
|
|
return buffer; |
|
|
|
} |
|
|
|
|
|
|
|
// heap allocates a copy of |string| and returns a pointer to it. |
|
|
|
static inline char* cpy(const char* string, Allocator* allocator = Allocator::GetDefault()) { |
|
|
|
static inline char* cpy(const char* string, Allocator& allocator = Allocator::GetDefault()) { |
|
|
|
ULE_TYPES_H_FTAG; |
|
|
|
u32 len = String::len(string); |
|
|
|
|
|
|
|
return String::cpy(string, len, allocator = Allocator::GetDefault()); |
|
|
|
} |
|
|
|
|
|
|
@ -222,6 +223,30 @@ public: |
|
|
|
return memeq(m1, m2, l1); |
|
|
|
} |
|
|
|
|
|
|
|
// assumes null termination. |
|
|
|
static inline bool LexographicComparisonASCII(const char* str1, const char* str2) { |
|
|
|
u32 min; |
|
|
|
|
|
|
|
const u32 l1 = String::len(str1); |
|
|
|
const u32 l2 = String::len(str2); |
|
|
|
if (l1 > l2) { |
|
|
|
min = l2; |
|
|
|
} else { |
|
|
|
min = l1; |
|
|
|
} |
|
|
|
|
|
|
|
for (u32 i = 0; i < min; i++) { |
|
|
|
if (str1[i] < str2[i]) { |
|
|
|
return true; |
|
|
|
|
|
|
|
} else if (str1[i] > str2[i]) { |
|
|
|
return false; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
return l1 < l2; |
|
|
|
} |
|
|
|
|
|
|
|
#ifdef _WIN32 |
|
|
|
static inline size_t wcharToChar(wchar_t* wstring, char* buffer, size_t maxBufferLength) { |
|
|
|
ULE_TYPES_H_FTAG; |
|
|
@ -239,12 +264,16 @@ public: |
|
|
|
|
|
|
|
static inline void memcpy(void* dest, void* src, u32 size) { |
|
|
|
ULE_TYPES_H_FTAG; |
|
|
|
u8* dest_ = (u8*) dest; |
|
|
|
u8* src_ = (u8*) src; |
|
|
|
// allowing c++ compilers to know we're invoking memcpy allows more aggressive optimizations, sometimes resulting in 8-9x speedup, |
|
|
|
// when compared to the horrible, commented out loop below. |
|
|
|
std::memcpy(dest, src, size); |
|
|
|
|
|
|
|
for (u32 i = 0; i < size; i++) { |
|
|
|
dest_[i] = src_[i]; |
|
|
|
} |
|
|
|
//u8* dest_ = (u8*) dest; |
|
|
|
//u8* src_ = (u8*) src; |
|
|
|
|
|
|
|
//for (u32 i = 0; i < size; i++) { |
|
|
|
// dest_[i] = src_[i]; |
|
|
|
//} |
|
|
|
} |
|
|
|
|
|
|
|
// replace all instances of |c1| in |string| with |c2| |
|
|
@ -340,7 +369,7 @@ public: |
|
|
|
// @TODO ALL OF THESE TRIMS |
|
|
|
//static inline char* trimStart(const char* str, u32 count); |
|
|
|
//static inline char* trimEnd(const char* str, u32 count); |
|
|
|
static inline char* trim(const char* str, u32 count, Allocator* allocator = Allocator::GetDefault()) { |
|
|
|
static inline char* trim(const char* str, u32 count, Allocator& allocator = Allocator::GetDefault()) { |
|
|
|
ULE_TYPES_H_FTAG; |
|
|
|
u32 length = String::len(str); |
|
|
|
|
|
|
@ -348,7 +377,7 @@ public: |
|
|
|
return (char*) ""; |
|
|
|
} |
|
|
|
|
|
|
|
char* buffer = (char*) allocator->mallocate(sizeof (char) * (length - 1), allocator->state); |
|
|
|
char* buffer = (char*) allocator.mallocate(sizeof (char) * (length - 1), allocator.state); |
|
|
|
|
|
|
|
u32 i = 0; |
|
|
|
for (; i < (length - count); i++) { |
|
|
@ -360,10 +389,10 @@ public: |
|
|
|
return buffer; |
|
|
|
} |
|
|
|
|
|
|
|
static inline char* asciiToLower(const char* str, Allocator* allocator = Allocator::GetDefault()) { |
|
|
|
static inline char* asciiToLower(const char* str, Allocator& allocator = Allocator::GetDefault()) { |
|
|
|
ULE_TYPES_H_FTAG; |
|
|
|
u32 length = String::len(str); |
|
|
|
char* buffer = (char*) allocator->mallocate(sizeof (char) * length + 1, allocator->state); |
|
|
|
char* buffer = (char*) allocator.mallocate(sizeof (char) * length + 1, allocator.state); |
|
|
|
u32 i = 0; |
|
|
|
for (; i < length; i++) { |
|
|
|
buffer[i] = String::ASCII_LOWER[str[i]]; |
|
|
@ -372,10 +401,10 @@ public: |
|
|
|
return buffer; |
|
|
|
} |
|
|
|
|
|
|
|
static inline char* asciiToUpper(const char* str, Allocator* allocator = Allocator::GetDefault()) { |
|
|
|
static inline char* asciiToUpper(const char* str, Allocator& allocator = Allocator::GetDefault()) { |
|
|
|
ULE_TYPES_H_FTAG; |
|
|
|
u32 length = String::len(str); |
|
|
|
char* buffer = (char*) allocator->mallocate(sizeof (char) * length + 1, allocator->state); |
|
|
|
char* buffer = (char*) allocator.mallocate(sizeof (char) * length + 1, allocator.state); |
|
|
|
u32 i = 0; |
|
|
|
for (; i < length; i++) { |
|
|
|
buffer[i] = String::ASCII_LOWER[str[i]]; |
|
|
@ -384,12 +413,12 @@ public: |
|
|
|
return buffer; |
|
|
|
} |
|
|
|
|
|
|
|
static inline char* concat(const char* str1, const char* str2, Allocator* allocator = Allocator::GetDefault()) { |
|
|
|
static inline char* concat(const char* str1, const char* str2, Allocator& allocator = Allocator::GetDefault()) { |
|
|
|
ULE_TYPES_H_FTAG; |
|
|
|
u32 l1 = String::len(str1); |
|
|
|
u32 l2 = String::len(str2); |
|
|
|
u32 newLength = l1 + l2; |
|
|
|
char* newBuffer = (char*) allocator->mallocate(sizeof (char) * newLength + 1, allocator->state); |
|
|
|
char* newBuffer = (char*) allocator.mallocate(sizeof (char) * newLength + 1, allocator.state); |
|
|
|
u32 i = 0; |
|
|
|
for (; i < newLength; i++) { |
|
|
|
if (i < l1) { |
|
|
@ -419,9 +448,9 @@ public: |
|
|
|
return String::write(dest, src, length); |
|
|
|
} |
|
|
|
|
|
|
|
static inline char* read(const char* buffer, u32 length, Allocator* allocator = Allocator::GetDefault()) { |
|
|
|
static inline char* read(const char* buffer, u32 length, Allocator& allocator = Allocator::GetDefault()) { |
|
|
|
ULE_TYPES_H_FTAG; |
|
|
|
char* tk = (char*) allocator->mallocate(sizeof (char) * length + 1, allocator->state); |
|
|
|
char* tk = (char*) allocator.mallocate(sizeof (char) * length + 1, allocator.state); |
|
|
|
u32 i = 0; |
|
|
|
while (i < length) { |
|
|
|
tk[i] = *(buffer + i); |
|
|
@ -431,6 +460,12 @@ public: |
|
|
|
return tk; |
|
|
|
} |
|
|
|
|
|
|
|
//--------------------------------------------------------------- |
|
|
|
// Begin String class type |
|
|
|
static inline void SetStringClassAllocator(Allocator* allocator) { |
|
|
|
_stringClassAllocator = allocator; |
|
|
|
} |
|
|
|
|
|
|
|
char* Data; // Point to LocalBuf() or heap allocated |
|
|
|
int Capacity : 21; // Max 2 MB |
|
|
|
int LocalBufSize : 10; // Max 1023 bytes |
|
|
@ -469,7 +504,7 @@ public: |
|
|
|
inline void set_ref(const char* src) { |
|
|
|
ULE_TYPES_H_FTAG; |
|
|
|
if (Owned && !is_using_local_buf()) |
|
|
|
STR_MEMFREE(Data); |
|
|
|
_stringClassAllocator->free(Data, null); |
|
|
|
Data = src ? (char*)src : EmptyBuffer; |
|
|
|
Capacity = 0; |
|
|
|
Owned = 0; |
|
|
@ -513,7 +548,7 @@ public: |
|
|
|
inline void clear() { |
|
|
|
ULE_TYPES_H_FTAG; |
|
|
|
if (Owned && !is_using_local_buf()) |
|
|
|
STR_MEMFREE(Data); |
|
|
|
_stringClassAllocator->free(Data, null); |
|
|
|
if (LocalBufSize) { |
|
|
|
Data = local_buf(); |
|
|
|
Data[0] = '\0'; |
|
|
@ -539,7 +574,7 @@ public: |
|
|
|
new_capacity = LocalBufSize; |
|
|
|
} else { |
|
|
|
// Disowned or LocalBuf -> Heap |
|
|
|
new_data = (char*)STR_MEMALLOC((size_t)new_capacity * sizeof(char)); |
|
|
|
new_data = (char*)_stringClassAllocator->mallocate((size_t)new_capacity * sizeof(char), null); |
|
|
|
} |
|
|
|
|
|
|
|
// string in Data might be longer than new_capacity if it wasn't owned, don't copy too much |
|
|
@ -551,7 +586,7 @@ public: |
|
|
|
new_data[new_capacity - 1] = 0; |
|
|
|
|
|
|
|
if (Owned && !is_using_local_buf()) |
|
|
|
STR_MEMFREE(Data); |
|
|
|
_stringClassAllocator->free(Data, null); |
|
|
|
|
|
|
|
Data = new_data; |
|
|
|
Capacity = new_capacity; |
|
|
@ -565,7 +600,7 @@ public: |
|
|
|
return; |
|
|
|
|
|
|
|
if (Owned && !is_using_local_buf()) |
|
|
|
STR_MEMFREE(Data); |
|
|
|
_stringClassAllocator->free(Data, null); |
|
|
|
|
|
|
|
if (new_capacity < LocalBufSize) { |
|
|
|
// Disowned -> LocalBuf |
|
|
@ -573,7 +608,7 @@ public: |
|
|
|
Capacity = LocalBufSize; |
|
|
|
} else { |
|
|
|
// Disowned or LocalBuf -> Heap |
|
|
|
Data = (char*)STR_MEMALLOC((size_t)new_capacity * sizeof(char)); |
|
|
|
Data = (char*)_stringClassAllocator->mallocate((size_t)new_capacity * sizeof(char), null); |
|
|
|
Capacity = new_capacity; |
|
|
|
} |
|
|
|
Owned = 1; |
|
|
@ -585,9 +620,9 @@ public: |
|
|
|
int new_capacity = length() + 1; |
|
|
|
if (Capacity <= new_capacity) return; |
|
|
|
|
|
|
|
char* new_data = (char*)STR_MEMALLOC((size_t)new_capacity * sizeof(char)); |
|
|
|
char* new_data = (char*)_stringClassAllocator->mallocate((size_t)new_capacity * sizeof(char), null); |
|
|
|
memcpy(new_data, Data, (size_t)new_capacity); |
|
|
|
STR_MEMFREE(Data); |
|
|
|
_stringClassAllocator->free(Data, null); |
|
|
|
Data = new_data; |
|
|
|
Capacity = new_capacity; |
|
|
|
} |
|
|
@ -725,7 +760,7 @@ public: |
|
|
|
inline ~String() |
|
|
|
{ |
|
|
|
if (Owned && !is_using_local_buf()) |
|
|
|
STR_MEMFREE(Data); |
|
|
|
if (_stringClassAllocator->free != null) ::_stringClassAllocator->free(Data, null); |
|
|
|
} |
|
|
|
|
|
|
|
protected: |
|
|
@ -831,12 +866,12 @@ public: |
|
|
|
new_data = (char*)this + sizeof(String); \ |
|
|
|
new_capacity = LocalBufSize; \ |
|
|
|
} else { \ |
|
|
|
new_data = (char*)STR_MEMALLOC((size_t)new_capacity * sizeof(char)); \ |
|
|
|
new_data = (char*)_stringClassAllocator->mallocate((size_t)new_capacity * sizeof(char), null); \ |
|
|
|
} \ |
|
|
|
strncpy(new_data, Data, (size_t)new_capacity - 1); \ |
|
|
|
new_data[new_capacity - 1] = 0; \ |
|
|
|
if (Owned && !is_using_local_buf()) \ |
|
|
|
STR_MEMFREE(Data); \ |
|
|
|
_stringClassAllocator->free(Data, null); \ |
|
|
|
Data = new_data; \ |
|
|
|
Capacity = new_capacity; \ |
|
|
|
Owned = 1; \ |
|
|
@ -846,14 +881,14 @@ public: |
|
|
|
if (new_capacity <= Capacity) \ |
|
|
|
return; \ |
|
|
|
if (Owned && !is_using_local_buf()) \ |
|
|
|
STR_MEMFREE(Data); \ |
|
|
|
_stringClassAllocator->free(Data, null); \ |
|
|
|
if (new_capacity < LocalBufSize) { \ |
|
|
|
Data = (char*)this + sizeof(String); \ |
|
|
|
Capacity = LocalBufSize; \ |
|
|
|
} else { \ |
|
|
|
while (Capacity < new_capacity) { \ |
|
|
|
Capacity = (s32)(Capacity * 1.5f); \ |
|
|
|
Data = (char*) STR_MEMALLOC((size_t) Capacity * sizeof(char)); \ |
|
|
|
Data = (char*) _stringClassAllocator->mallocate((size_t) Capacity * sizeof(char), null); \ |
|
|
|
} \ |
|
|
|
} \ |
|
|
|
Owned = 1; \ |
|
|
|