mirror of
https://github.com/Ed94/gencpp.git
synced 2025-06-30 19:01:02 -07:00
WIP(broken): Converting base library to use c-linkage symbols only
This commit is contained in:
@ -31,23 +31,23 @@ usize array_grow_formula(ssize value);
|
||||
|
||||
template<class Type> Array(Type) array_init (AllocatorInfo allocator);
|
||||
template<class Type> Array(Type) array_init_reserve(AllocatorInfo allocator, ssize capacity);
|
||||
template<class Type> bool append (Array(Type)* array, Array(Type) other);
|
||||
template<class Type> bool append (Array(Type)* array, Type value);
|
||||
template<class Type> bool append (Array(Type)* array, Type* items, usize item_num);
|
||||
template<class Type> bool append_at (Array(Type)* array, Type item, usize idx);
|
||||
template<class Type> bool append_at (Array(Type)* array, Type* items, usize item_num, usize idx);
|
||||
template<class Type> Type* back (Array(Type) array);
|
||||
template<class Type> void clear (Array(Type) array);
|
||||
template<class Type> bool fill (Array(Type) array, usize begin, usize end, Type value);
|
||||
template<class Type> void free (Array(Type)* array);
|
||||
template<class Type> bool grow (Array(Type)* array, usize min_capacity);
|
||||
template<class Type> usize num (Array(Type) array);
|
||||
template<class Type> void pop (Array(Type) array);
|
||||
template<class Type> void remove_at (Array(Type) array, usize idx);
|
||||
template<class Type> bool reserve (Array(Type)* array, usize new_capacity);
|
||||
template<class Type> bool resize (Array(Type)* array, usize num);
|
||||
template<class Type> bool set_capacity (Array(Type)* array, usize new_capacity);
|
||||
template<class Type> ArrayHeader* get_header (Array(Type) array);
|
||||
template<class Type> bool array_append (Array(Type)* array, Array(Type) other);
|
||||
template<class Type> bool array_append (Array(Type)* array, Type value);
|
||||
template<class Type> bool array_append (Array(Type)* array, Type* items, usize item_num);
|
||||
template<class Type> bool array_append_at (Array(Type)* array, Type item, usize idx);
|
||||
template<class Type> bool array_append_at (Array(Type)* array, Type* items, usize item_num, usize idx);
|
||||
template<class Type> Type* array_back (Array(Type) array);
|
||||
template<class Type> void array_clear (Array(Type) array);
|
||||
template<class Type> bool array_fill (Array(Type) array, usize begin, usize end, Type value);
|
||||
template<class Type> void array_free (Array(Type)* array);
|
||||
template<class Type> bool arary_grow (Array(Type)* array, usize min_capacity);
|
||||
template<class Type> usize array_num (Array(Type) array);
|
||||
template<class Type> void arary_pop (Array(Type) array);
|
||||
template<class Type> void arary_remove_at (Array(Type) array, usize idx);
|
||||
template<class Type> bool arary_reserve (Array(Type)* array, usize new_capacity);
|
||||
template<class Type> bool arary_resize (Array(Type)* array, usize num);
|
||||
template<class Type> bool arary_set_capacity(Array(Type)* array, usize new_capacity);
|
||||
template<class Type> ArrayHeader* arary_get_header (Array(Type) array);
|
||||
|
||||
struct ArrayHeader {
|
||||
AllocatorInfo Allocator;
|
||||
@ -66,23 +66,23 @@ struct Array
|
||||
forceinline static Array init_reserve(AllocatorInfo allocator, ssize capacity) { return GEN_NS array_init_reserve<Type>(allocator, capacity); }
|
||||
forceinline static usize grow_formula(ssize value) { return GEN_NS array_grow_formula<Type>(value); }
|
||||
|
||||
forceinline bool append(Array other) { return GEN_NS append<Type>(this, other); }
|
||||
forceinline bool append(Type value) { return GEN_NS append<Type>(this, value); }
|
||||
forceinline bool append(Type* items, usize item_num) { return GEN_NS append<Type>(this, items, item_num); }
|
||||
forceinline bool append_at(Type item, usize idx) { return GEN_NS append_at<Type>(this, item, idx); }
|
||||
forceinline bool append_at(Type* items, usize item_num, usize idx) { return GEN_NS append_at<Type>(this, items, item_num, idx); }
|
||||
forceinline Type* back() { return GEN_NS back<Type>(* this); }
|
||||
forceinline void clear() { GEN_NS clear<Type>(* this); }
|
||||
forceinline bool fill(usize begin, usize end, Type value) { return GEN_NS fill<Type>(* this, begin, end, value); }
|
||||
forceinline void free() { GEN_NS free<Type>(this); }
|
||||
forceinline ArrayHeader* get_header() { return GEN_NS get_header<Type>(* this); }
|
||||
forceinline bool grow(usize min_capacity) { return GEN_NS grow<Type>(this, min_capacity); }
|
||||
forceinline usize num() { return GEN_NS num<Type>(*this); }
|
||||
forceinline void pop() { GEN_NS pop<Type>(* this); }
|
||||
forceinline void remove_at(usize idx) { GEN_NS remove_at<Type>(* this, idx); }
|
||||
forceinline bool reserve(usize new_capacity) { return GEN_NS reserve<Type>(this, new_capacity); }
|
||||
forceinline bool resize(usize num) { return GEN_NS resize<Type>(this, num); }
|
||||
forceinline bool set_capacity(usize new_capacity) { return GEN_NS set_capacity<Type>(this, new_capacity); }
|
||||
forceinline bool append(Array other) { return GEN_NS array_append<Type>(this, other); }
|
||||
forceinline bool append(Type value) { return GEN_NS array_append<Type>(this, value); }
|
||||
forceinline bool append(Type* items, usize item_num) { return GEN_NS array_append<Type>(this, items, item_num); }
|
||||
forceinline bool append_at(Type item, usize idx) { return GEN_NS array_append_at<Type>(this, item, idx); }
|
||||
forceinline bool append_at(Type* items, usize item_num, usize idx) { return GEN_NS array_append_at<Type>(this, items, item_num, idx); }
|
||||
forceinline Type* back() { return GEN_NS array_back<Type>(* this); }
|
||||
forceinline void clear() { GEN_NS array_clear<Type>(* this); }
|
||||
forceinline bool fill(usize begin, usize end, Type value) { return GEN_NS array_fill<Type>(* this, begin, end, value); }
|
||||
forceinline void free() { GEN_NS array_free<Type>(this); }
|
||||
forceinline ArrayHeader* get_header() { return GEN_NS array_get_header<Type>(* this); }
|
||||
forceinline bool grow(usize min_capacity) { return GEN_NS array_grow<Type>(this, min_capacity); }
|
||||
forceinline usize num() { return GEN_NS array_num<Type>(*this); }
|
||||
forceinline void pop() { GEN_NS array_pop<Type>(* this); }
|
||||
forceinline void remove_at(usize idx) { GEN_NS array_remove_at<Type>(* this, idx); }
|
||||
forceinline bool reserve(usize new_capacity) { return GEN_NS array_reserve<Type>(this, new_capacity); }
|
||||
forceinline bool resize(usize num) { return GEN_NS array_resize<Type>(this, num); }
|
||||
forceinline bool set_capacity(usize new_capacity) { return GEN_NS array_set_capacity<Type>(this, new_capacity); }
|
||||
#pragma endregion Member Mapping
|
||||
|
||||
forceinline operator Type*() { return Data; }
|
||||
@ -108,14 +108,14 @@ template<class Type> bool resize(Array<Type>& array, usize num)
|
||||
template<class Type> bool set_capacity(Array<Type>& array, usize new_capacity) { return GEN_NS set_capacity( & array, new_capacity); }
|
||||
|
||||
template<class Type> forceinline Type* begin(Array<Type>& array) { return array; }
|
||||
template<class Type> forceinline Type* end(Array<Type>& array) { return array + get_header(array)->Num; }
|
||||
template<class Type> forceinline Type* end(Array<Type>& array) { return array + array_get_header(array)->Num; }
|
||||
template<class Type> forceinline Type* next(Array<Type>& array, Type* entry) { return entry + 1; }
|
||||
#else
|
||||
template<class Type> forceinline Type* begin(Array<Type> array) { return array; }
|
||||
template<class Type> forceinline Type* end(Array<Type> array) { return array + get_header(array)->Num; }
|
||||
template<class Type> forceinline Type* next(Array<Type> array, Type* entry) { return entry + 1; }
|
||||
#endif
|
||||
|
||||
template<class Type> forceinline Type* array_begin(Array<Type> array) { return array; }
|
||||
template<class Type> forceinline Type* array_end(Array<Type> array) { return array + array_get_header(array)->Num; }
|
||||
template<class Type> forceinline Type* array_next(Array<Type> array, Type* entry) { return entry + 1; }
|
||||
|
||||
template<class Type> inline
|
||||
Array<Type> array_init(AllocatorInfo allocator) {
|
||||
return array_init_reserve<Type>(allocator, array_grow_formula(0));
|
||||
@ -141,20 +141,20 @@ usize array_grow_formula(ssize value) {
|
||||
}
|
||||
|
||||
template<class Type> inline
|
||||
bool append(Array<Type>* array, Array<Type> other) {
|
||||
bool array_append(Array<Type>* array, Array<Type> other) {
|
||||
return append(array, other, num(other));
|
||||
}
|
||||
|
||||
template<class Type> inline
|
||||
bool append(Array<Type>* array, Type value)
|
||||
bool array_append(Array<Type>* array, Type value)
|
||||
{
|
||||
ArrayHeader* header = get_header(* array);
|
||||
ArrayHeader* header = array_get_header(* array);
|
||||
|
||||
if (header->Num == header->Capacity)
|
||||
{
|
||||
if ( ! grow(array, header->Capacity))
|
||||
if ( ! array_grow(array, header->Capacity))
|
||||
return false;
|
||||
header = get_header(* array);
|
||||
header = array_get_header(* array);
|
||||
}
|
||||
|
||||
(*array)[ header->Num] = value;
|
||||
@ -164,15 +164,15 @@ bool append(Array<Type>* array, Type value)
|
||||
}
|
||||
|
||||
template<class Type> inline
|
||||
bool append(Array<Type>* array, Type* items, usize item_num)
|
||||
bool array_append(Array<Type>* array, Type* items, usize item_num)
|
||||
{
|
||||
ArrayHeader* header = get_header(array);
|
||||
ArrayHeader* header = array_get_header(array);
|
||||
|
||||
if (header->Num + item_num > header->Capacity)
|
||||
{
|
||||
if ( ! grow(array, header->Capacity + item_num))
|
||||
return false;
|
||||
header = get_header(array);
|
||||
header = array_get_header(array);
|
||||
}
|
||||
|
||||
mem_copy((Type*)array + header->Num, items, item_num * sizeof(Type));
|
||||
@ -182,9 +182,9 @@ bool append(Array<Type>* array, Type* items, usize item_num)
|
||||
}
|
||||
|
||||
template<class Type> inline
|
||||
bool append_at(Array<Type>* array, Type item, usize idx)
|
||||
bool array_append_at(Array<Type>* array, Type item, usize idx)
|
||||
{
|
||||
ArrayHeader* header = get_header(* array);
|
||||
ArrayHeader* header = array_get_header(* array);
|
||||
|
||||
ssize slot = idx;
|
||||
if (slot >= header->Num)
|
||||
@ -195,10 +195,10 @@ bool append_at(Array<Type>* array, Type item, usize idx)
|
||||
|
||||
if (header->Capacity < header->Num + 1)
|
||||
{
|
||||
if ( ! grow(array, header->Capacity + 1))
|
||||
if ( ! array_grow(array, header->Capacity + 1))
|
||||
return false;
|
||||
|
||||
header = get_header(* array);
|
||||
header = array_get_header(* array);
|
||||
}
|
||||
|
||||
Type* target = &(*array)[slot];
|
||||
@ -206,13 +206,13 @@ bool append_at(Array<Type>* array, Type item, usize idx)
|
||||
mem_move(target + 1, target, (header->Num - slot) * sizeof(Type));
|
||||
header->Num++;
|
||||
|
||||
header = get_header(* array);
|
||||
header = array_get_header(* array);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template<class Type> inline
|
||||
bool append_at(Array<Type>* array, Type* items, usize item_num, usize idx)
|
||||
bool array_append_at(Array<Type>* array, Type* items, usize item_num, usize idx)
|
||||
{
|
||||
ArrayHeader* header = get_header(array);
|
||||
|
||||
@ -240,11 +240,11 @@ bool append_at(Array<Type>* array, Type* items, usize item_num, usize idx)
|
||||
}
|
||||
|
||||
template<class Type> inline
|
||||
Type* back(Array<Type>* array)
|
||||
Type* array_back(Array<Type>* array)
|
||||
{
|
||||
GEN_ASSERT(array != nullptr);
|
||||
|
||||
ArrayHeader* header = get_header(* array);
|
||||
ArrayHeader* header = array_get_header(* array);
|
||||
if (header->Num <= 0)
|
||||
return nullptr;
|
||||
|
||||
@ -252,15 +252,15 @@ Type* back(Array<Type>* array)
|
||||
}
|
||||
|
||||
template<class Type> inline
|
||||
void clear(Array<Type> array) {
|
||||
ArrayHeader* header = get_header(array);
|
||||
void array_clear(Array<Type> array) {
|
||||
ArrayHeader* header = array_get_header(array);
|
||||
header->Num = 0;
|
||||
}
|
||||
|
||||
template<class Type> inline
|
||||
bool fill(Array<Type> array, usize begin, usize end, Type value)
|
||||
bool array_fill(Array<Type> array, usize begin, usize end, Type value)
|
||||
{
|
||||
ArrayHeader* header = get_header(array);
|
||||
ArrayHeader* header = array_get_header(array);
|
||||
|
||||
if (begin < 0 || end > header->Num)
|
||||
return false;
|
||||
@ -274,49 +274,49 @@ bool fill(Array<Type> array, usize begin, usize end, Type value)
|
||||
}
|
||||
|
||||
template<class Type> inline
|
||||
void free(Array<Type>* array) {
|
||||
void array_free(Array<Type>* array) {
|
||||
GEN_ASSERT(array != nullptr);
|
||||
ArrayHeader* header = get_header(* array);
|
||||
GEN_NS free(header->Allocator, header);
|
||||
ArrayHeader* header = array_get_header(* array);
|
||||
allocator_free(header->Allocator, header);
|
||||
Type** Data = (Type**)array;
|
||||
*Data = nullptr;
|
||||
}
|
||||
|
||||
template<class Type> forceinline
|
||||
ArrayHeader* get_header(Array<Type> array) {
|
||||
ArrayHeader* array_get_header(Array<Type> array) {
|
||||
Type* Data = array;
|
||||
|
||||
using NonConstType = TRemoveConst<Type>;
|
||||
return rcast(ArrayHeader*, const_cast<NonConstType*>(Data)) - 1;
|
||||
}
|
||||
template<class Type> inline
|
||||
bool grow(Array<Type>* array, usize min_capacity)
|
||||
bool array_grow(Array<Type>* array, usize min_capacity)
|
||||
{
|
||||
ArrayHeader* header = get_header(* array);
|
||||
ArrayHeader* header = array_get_header(* array);
|
||||
usize new_capacity = array_grow_formula(header->Capacity);
|
||||
|
||||
if (new_capacity < min_capacity)
|
||||
new_capacity = min_capacity;
|
||||
|
||||
return set_capacity(array, new_capacity);
|
||||
return array_set_capacity(array, new_capacity);
|
||||
}
|
||||
|
||||
template<class Type> inline
|
||||
usize num(Array<Type> array) {
|
||||
return get_header(array)->Num;
|
||||
usize array_num(Array<Type> array) {
|
||||
return array_get_header(array)->Num;
|
||||
}
|
||||
|
||||
template<class Type> inline
|
||||
void pop(Array<Type> array) {
|
||||
ArrayHeader* header = get_header(array);
|
||||
void array_pop(Array<Type> array) {
|
||||
ArrayHeader* header = array_get_header(array);
|
||||
GEN_ASSERT(header->Num > 0);
|
||||
header->Num--;
|
||||
}
|
||||
|
||||
template<class Type> inline
|
||||
void remove_at(Array<Type> array, usize idx)
|
||||
void array_remove_at(Array<Type> array, usize idx)
|
||||
{
|
||||
ArrayHeader* header = get_header(array);
|
||||
ArrayHeader* header = array_get_header(array);
|
||||
GEN_ASSERT(idx < header->Num);
|
||||
|
||||
mem_move(array + idx, array + idx + 1, sizeof(Type) * (header->Num - idx - 1));
|
||||
@ -324,9 +324,9 @@ void remove_at(Array<Type> array, usize idx)
|
||||
}
|
||||
|
||||
template<class Type> inline
|
||||
bool reserve(Array<Type>* array, usize new_capacity)
|
||||
bool array_reserve(Array<Type>* array, usize new_capacity)
|
||||
{
|
||||
ArrayHeader* header = get_header(array);
|
||||
ArrayHeader* header = array_get_header(array);
|
||||
|
||||
if (header->Capacity < new_capacity)
|
||||
return set_capacity(array, new_capacity);
|
||||
@ -335,14 +335,14 @@ bool reserve(Array<Type>* array, usize new_capacity)
|
||||
}
|
||||
|
||||
template<class Type> inline
|
||||
bool resize(Array<Type>* array, usize num)
|
||||
bool array_resize(Array<Type>* array, usize num)
|
||||
{
|
||||
ArrayHeader* header = get_header(* array);
|
||||
ArrayHeader* header = array_get_header(* array);
|
||||
|
||||
if (header->Capacity < num) {
|
||||
if (! grow( array, num))
|
||||
if (! array_grow( array, num))
|
||||
return false;
|
||||
header = get_header(* array);
|
||||
header = array_get_header(* array);
|
||||
}
|
||||
|
||||
header->Num = num;
|
||||
@ -350,9 +350,9 @@ bool resize(Array<Type>* array, usize num)
|
||||
}
|
||||
|
||||
template<class Type> inline
|
||||
bool set_capacity(Array<Type>* array, usize new_capacity)
|
||||
bool array_set_capacity(Array<Type>* array, usize new_capacity)
|
||||
{
|
||||
ArrayHeader* header = get_header(* array);
|
||||
ArrayHeader* header = array_get_header(* array);
|
||||
|
||||
if (new_capacity == header->Capacity)
|
||||
return true;
|
||||
@ -373,13 +373,15 @@ bool set_capacity(Array<Type>* array, usize new_capacity)
|
||||
|
||||
new_header->Capacity = new_capacity;
|
||||
|
||||
GEN_NS free(header->Allocator, header);
|
||||
allocator_free(header->Allocator, header);
|
||||
|
||||
Type** Data = (Type**)array;
|
||||
* Data = rcast(Type*, new_header + 1);
|
||||
return true;
|
||||
}
|
||||
|
||||
#define array_init_reserve(type, allocator, cap) array_init_reserve<type>(allocator, cap)
|
||||
|
||||
#pragma endregion Array
|
||||
|
||||
// TODO(Ed) : This thing needs ALOT of work.
|
||||
@ -471,9 +473,9 @@ HashTable<Type> hashtable_init_reserve(AllocatorInfo allocator, usize num)
|
||||
HashTable<Type> result = { { nullptr }, { nullptr } };
|
||||
|
||||
result.Hashes = array_init_reserve<ssize>(allocator, num);
|
||||
get_header(result.Hashes)->Num = num;
|
||||
resize(& result.Hashes, num);
|
||||
fill<ssize>(result.Hashes, 0, num, -1);
|
||||
array_get_header(result.Hashes)->Num = num;
|
||||
array_resize(& result.Hashes, num);
|
||||
array_fill<ssize>(result.Hashes, 0, num, -1);
|
||||
|
||||
result.Entries = array_init_reserve<HashTableEntry<Type>>(allocator, num);
|
||||
return result;
|
||||
@ -481,15 +483,15 @@ HashTable<Type> hashtable_init_reserve(AllocatorInfo allocator, usize num)
|
||||
|
||||
template<typename Type> inline
|
||||
void clear(HashTable<Type> table) {
|
||||
clear(table.Entries);
|
||||
fill<ssize>(table.Hashes, 0, num(table.Hashes), -1);
|
||||
array_clear(table.Entries);
|
||||
array_fill(table.Hashes, 0, array_num(table.Hashes), (ssize)-1);
|
||||
}
|
||||
|
||||
template<typename Type> inline
|
||||
void destroy(HashTable<Type>* table) {
|
||||
if (table->Hashes && get_header(table->Hashes)->Capacity) {
|
||||
free(& table->Hashes);
|
||||
free(& table->Entries);
|
||||
if (table->Hashes && array_get_header(table->Hashes)->Capacity) {
|
||||
array_free(& table->Hashes);
|
||||
array_free(& table->Entries);
|
||||
}
|
||||
}
|
||||
|
||||
@ -522,7 +524,7 @@ void map_mut(HashTable<Type> table, void (*map_proc)(u64 key, Type* value)) {
|
||||
|
||||
template<typename Type> inline
|
||||
void grow(HashTable<Type>* table) {
|
||||
ssize new_num = array_grow_formula(num(table->Entries));
|
||||
ssize new_num = array_grow_formula( array_num(table->Entries));
|
||||
rehash(table, new_num);
|
||||
}
|
||||
|
||||
@ -530,9 +532,9 @@ template<typename Type> inline
|
||||
void rehash(HashTable<Type>* table, ssize new_num)
|
||||
{
|
||||
ssize last_added_index;
|
||||
HashTable<Type> new_ht = hashtable_init_reserve<Type>(get_header(table->Hashes)->Allocator, new_num);
|
||||
HashTable<Type> new_ht = hashtable_init_reserve<Type>( array_get_header(table->Hashes)->Allocator, new_num);
|
||||
|
||||
for (ssize idx = 0; idx < ssize(num(table->Entries)); ++idx)
|
||||
for (ssize idx = 0; idx < ssize( array_num(table->Entries)); ++idx)
|
||||
{
|
||||
HashTableFindResult find_result;
|
||||
HashTableEntry<Type>& entry = table->Entries[idx];
|
||||
@ -639,8 +641,8 @@ ssize add_entry(HashTable<Type>* table, u64 key) {
|
||||
ssize idx;
|
||||
HashTableEntry<Type> entry = { key, -1 };
|
||||
|
||||
idx = num(table->Entries);
|
||||
append( & table->Entries, entry);
|
||||
idx = array_num(table->Entries);
|
||||
array_append( & table->Entries, entry);
|
||||
return idx;
|
||||
}
|
||||
|
||||
@ -649,9 +651,9 @@ HashTableFindResult find(HashTable<Type> table, u64 key)
|
||||
{
|
||||
HashTableFindResult result = { -1, -1, -1 };
|
||||
|
||||
if (num(table.Hashes) > 0)
|
||||
if (array_num(table.Hashes) > 0)
|
||||
{
|
||||
result.HashIndex = key % num(table.Hashes);
|
||||
result.HashIndex = key % array_num(table.Hashes);
|
||||
result.EntryIndex = table.Hashes[result.HashIndex];
|
||||
|
||||
while (result.EntryIndex >= 0)
|
||||
@ -669,8 +671,8 @@ HashTableFindResult find(HashTable<Type> table, u64 key)
|
||||
|
||||
template<typename Type> inline
|
||||
bool full(HashTable<Type> table) {
|
||||
usize critical_load = usize(HashTable_CriticalLoadScale * f32(num(table.Hashes)));
|
||||
b32 result = num(table.Entries) > critical_load;
|
||||
usize critical_load = usize(HashTable_CriticalLoadScale * f32(array_num(table.Hashes)));
|
||||
b32 result = array_num(table.Entries) > critical_load;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -56,8 +56,10 @@
|
||||
while (0)
|
||||
#endif
|
||||
|
||||
GEN_API_C_BEGIN
|
||||
void assert_handler( char const* condition, char const* file, s32 line, char const* msg, ... );
|
||||
s32 assert_crash( char const* condition );
|
||||
void process_exit( u32 code );
|
||||
GEN_API_C_END
|
||||
|
||||
#pragma endregion Debug
|
||||
|
@ -36,7 +36,7 @@ wchar_t* _alloc_utf8_to_ucs2( AllocatorInfo a, char const* text, ssize* w_len_ )
|
||||
w_len1 = MultiByteToWideChar( CP_UTF8, MB_ERR_INVALID_CHARS, text, scast( int, len), w_text, scast( int, w_len) );
|
||||
if ( w_len1 == 0 )
|
||||
{
|
||||
free( a, w_text );
|
||||
allocator_free( a, w_text );
|
||||
if ( w_len_ )
|
||||
*w_len_ = 0;
|
||||
return NULL;
|
||||
@ -145,7 +145,7 @@ GEN_FILE_OPEN_PROC( _win32_file_open )
|
||||
w_text = _alloc_utf8_to_ucs2( heap(), filename, NULL );
|
||||
handle = CreateFileW( w_text, desired_access, FILE_SHARE_READ | FILE_SHARE_DELETE, NULL, creation_disposition, FILE_ATTRIBUTE_NORMAL, NULL );
|
||||
|
||||
free( heap(), w_text );
|
||||
allocator_free( heap(), w_text );
|
||||
|
||||
if ( handle == INVALID_HANDLE_VALUE )
|
||||
{
|
||||
@ -340,7 +340,7 @@ FileError file_close( FileInfo* f )
|
||||
return EFileError_INVALID;
|
||||
|
||||
if ( f->filename )
|
||||
free( heap(), ccast( char*, f->filename ));
|
||||
allocator_free( heap(), ccast( char*, f->filename ));
|
||||
|
||||
#if defined( GEN_SYSTEM_WINDOWS )
|
||||
if ( f->fd.p == INVALID_HANDLE_VALUE )
|
||||
@ -540,7 +540,7 @@ b8 file_stream_open( FileInfo* file, AllocatorInfo allocator, u8* buffer, ssize
|
||||
mem_copy( d->buf, buffer, size );
|
||||
d->cap = size;
|
||||
|
||||
get_header(arr)->Num = size;
|
||||
array_get_header(arr)->Num = size;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -610,9 +610,9 @@ GEN_FILE_WRITE_AT_PROC( _memory_file_write )
|
||||
{
|
||||
Array<u8> arr = { d->buf };
|
||||
|
||||
if ( get_header(arr)->Capacity < usize(new_cap) )
|
||||
if ( array_get_header(arr)->Capacity < usize(new_cap) )
|
||||
{
|
||||
if ( ! grow( & arr, ( s64 )( new_cap ) ) )
|
||||
if ( ! array_grow( & arr, ( s64 )( new_cap ) ) )
|
||||
return false;
|
||||
d->buf = arr;
|
||||
}
|
||||
@ -626,7 +626,7 @@ GEN_FILE_WRITE_AT_PROC( _memory_file_write )
|
||||
|
||||
mem_copy( d->buf + offset + rwlen, pointer_add_const( buffer, rwlen ), extralen );
|
||||
d->cap = new_cap;
|
||||
get_header(arr)->Capacity = new_cap;
|
||||
array_get_header(arr)->Capacity = new_cap;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -647,10 +647,10 @@ GEN_FILE_CLOSE_PROC( _memory_file_close )
|
||||
if ( d->flags & EFileStream_CLONE_WRITABLE )
|
||||
{
|
||||
Array<u8> arr = { d->buf };
|
||||
free(& arr);
|
||||
array_free(& arr);
|
||||
}
|
||||
|
||||
free( allocator, d );
|
||||
allocator_free( allocator, d );
|
||||
}
|
||||
|
||||
FileOperations const memory_file_operations = { _memory_file_read, _memory_file_write, _memory_file_seek, _memory_file_close };
|
||||
|
@ -49,7 +49,7 @@ typedef struct FileOperations FileOperations;
|
||||
|
||||
#define GEN_FILE_OPEN_PROC( name ) FileError name( FileDescriptor* fd, FileOperations* ops, FileMode mode, char const* filename )
|
||||
#define GEN_FILE_READ_AT_PROC( name ) b32 name( FileDescriptor fd, void* buffer, ssize size, s64 offset, ssize* bytes_read, b32 stop_at_newline )
|
||||
#define GEN_FILE_WRITE_AT_PROC( name ) b32 name( FileDescriptor fd, void const* buffer, ssize size, s64 offset, ssize* bytes_written )
|
||||
#define GEN_FILE_WRITE_AT_PROC( name ) b32 name( FileDescriptor fd, mem_ptr_const buffer, ssize size, s64 offset, ssize* bytes_written )
|
||||
#define GEN_FILE_SEEK_PROC( name ) b32 name( FileDescriptor fd, s64 offset, SeekWhenceType whence, s64* new_offset )
|
||||
#define GEN_FILE_CLOSE_PROC( name ) void name( FileDescriptor fd )
|
||||
|
||||
|
@ -5,7 +5,11 @@
|
||||
|
||||
#pragma region Hashing
|
||||
|
||||
GEN_API_C_BEGIN
|
||||
|
||||
u32 crc32( void const* data, ssize len );
|
||||
u64 crc64( void const* data, ssize len );
|
||||
|
||||
GEN_API_C_END
|
||||
|
||||
#pragma endregion Hashing
|
||||
|
@ -14,17 +14,12 @@
|
||||
#define local_persist static // Local Persisting variables
|
||||
#endif
|
||||
|
||||
#ifndef api_c
|
||||
#define api_c extern "C"
|
||||
#endif
|
||||
|
||||
#ifndef bit
|
||||
#define bit( Value ) ( 1 << Value )
|
||||
#define bitfield_is_equal( Type, Field, Mask ) ( (Type(Mask) & Type(Field)) == Type(Mask) )
|
||||
#endif
|
||||
|
||||
|
||||
#if ! GEN_C_COMPILER
|
||||
#if GEN_COMPILER_CPP
|
||||
# ifndef cast
|
||||
# define cast( type, value ) (tmpl_cast<type>( value ))
|
||||
# endif
|
||||
@ -198,7 +193,7 @@
|
||||
# define GEN_SUPPORT_CPP_MEMBER_FEATURES 0
|
||||
#endif
|
||||
|
||||
#if !defined(typeof) && (!GEN_COMPILER_C || __STDC_VERSION__ < 202311L)
|
||||
#if ! defined(typeof) && (!GEN_COMPILER_C || __STDC_VERSION__ < 202311L)
|
||||
# if ! GEN_COMPILER_C
|
||||
# define typeof decltype
|
||||
# elif defined(_MSC_VER)
|
||||
@ -210,9 +205,15 @@
|
||||
# endif
|
||||
#endif
|
||||
|
||||
// This is intended to only really be used internally or with the C-library variant
|
||||
// C++ users can just use the for-range directly.
|
||||
#define foreach(Type, entry_id, iterable) for ( Type entry_id = begin(iterable); entry_id != end(iterable); entry_id = next(iterable, entry_id) )
|
||||
#ifndef GEN_API_C_BEGIN
|
||||
# if GEN_COMPILER_C
|
||||
# define GEN_API_C_BEGIN
|
||||
# define GEN_API_C_END
|
||||
# else
|
||||
# define GEN_API_C_BEGIN extern "C" {
|
||||
# define GEN_API_C_END }
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if GEN_COMPILER_C
|
||||
# if __STDC_VERSION__ >= 202311L
|
||||
@ -230,7 +231,7 @@
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if ! defined(GEN_PARAM_DEFAULT) && ! GEN_COMPILER_C
|
||||
#if ! defined(GEN_PARAM_DEFAULT) && GEN_COMPILER_CPP
|
||||
# define GEN_PARAM_DEFAULT = {}
|
||||
#else
|
||||
# define GEN_PARAM_DEFAULT
|
||||
|
@ -346,7 +346,7 @@ void* arena_allocator_proc( void* allocator_data, AllocType type, ssize size, ss
|
||||
case EAllocation_ALLOC :
|
||||
{
|
||||
void* end = pointer_add( arena->PhysicalStart, arena->TotalUsed );
|
||||
ssize total_size = align_forward_i64( size, alignment );
|
||||
ssize total_size = align_forward_s64( size, alignment );
|
||||
|
||||
// NOTE: Out of memory
|
||||
if ( arena->TotalUsed + total_size > (ssize) arena->TotalSize )
|
||||
|
@ -22,6 +22,8 @@ void swap( Type& a, Type& b )
|
||||
b = tmp;
|
||||
}
|
||||
|
||||
GEN_API_C_BEGIN
|
||||
|
||||
//! Checks if value is power of 2.
|
||||
b32 is_power_of_two( ssize x );
|
||||
|
||||
@ -29,7 +31,7 @@ b32 is_power_of_two( ssize x );
|
||||
void* align_forward( void* ptr, ssize alignment );
|
||||
|
||||
//! Aligns value to a specified alignment.
|
||||
s64 align_forward_i64( s64 value, ssize alignment );
|
||||
s64 align_forward_by_value( s64 value, ssize alignment );
|
||||
|
||||
//! Moves pointer forward by bytes.
|
||||
void* pointer_add( void* ptr, ssize bytes );
|
||||
@ -100,7 +102,7 @@ void* alloc( AllocatorInfo a, ssize size );
|
||||
void* alloc_align( AllocatorInfo a, ssize size, ssize alignment );
|
||||
|
||||
//! Free allocated memory.
|
||||
void free( AllocatorInfo a, void* ptr );
|
||||
void allocator_free( AllocatorInfo a, void* ptr );
|
||||
|
||||
//! Free all memory allocated by an allocator.
|
||||
void free_all( AllocatorInfo a );
|
||||
@ -142,11 +144,12 @@ constexpr AllocatorInfo heap( void ) { AllocatorInfo allocator = { heap_allocato
|
||||
//! Helper to free memory allocated by heap allocator.
|
||||
#define mfree( ptr ) free( heap(), ptr )
|
||||
|
||||
struct VirtualMemory
|
||||
struct VirtualMemory_Def
|
||||
{
|
||||
void* data;
|
||||
ssize size;
|
||||
};
|
||||
typedef struct VirtualMemory_Def VirtualMemory;
|
||||
|
||||
//! Initialize virtual memory from existing data.
|
||||
VirtualMemory vm_from_memory( void* data, ssize size );
|
||||
@ -164,15 +167,16 @@ b32 vm_free( VirtualMemory vm );
|
||||
VirtualMemory vm_trim( VirtualMemory vm, ssize lead_size, ssize size );
|
||||
|
||||
//! Purge virtual memory.
|
||||
b32 gen_vm_purge( VirtualMemory vm );
|
||||
b32 vm_purge( VirtualMemory vm );
|
||||
|
||||
//! Retrieve VM's page size and alignment.
|
||||
ssize gen_virtual_memory_page_size( ssize* alignment_out );
|
||||
ssize virtual_memory_page_size( ssize* alignment_out );
|
||||
|
||||
#pragma region Arena
|
||||
struct Arena;
|
||||
struct Arena_Def;
|
||||
typedef struct Arena_Def Arena;
|
||||
|
||||
AllocatorInfo allocator_info( Arena* arena );
|
||||
AllocatorInfo arena_allocator_info( Arena* arena );
|
||||
|
||||
// Remove static keyword and rename allocator_proc
|
||||
void* arena_allocator_proc(void* allocator_data, AllocType type, ssize size, ssize alignment, void* old_memory, ssize old_size, u64 flags);
|
||||
@ -181,18 +185,13 @@ void* arena_allocator_proc(void* allocator_data, AllocType type, ssize size, ssi
|
||||
Arena arena_init_from_allocator(AllocatorInfo backing, ssize size);
|
||||
Arena arena_init_from_memory ( void* start, ssize size );
|
||||
|
||||
Arena init_sub (Arena* parent, ssize size);
|
||||
ssize alignment_of (Arena* arena, ssize alignment);
|
||||
void free (Arena* arena);
|
||||
ssize size_remaining(Arena* arena, ssize alignment);
|
||||
Arena arena_init_sub (Arena* parent, ssize size);
|
||||
ssize arena_alignment_of (Arena* arena, ssize alignment);
|
||||
void arena_check (Arena* arena);
|
||||
void arena_free (Arena* arena);
|
||||
ssize arena_size_remaining(Arena* arena, ssize alignment);
|
||||
|
||||
// This id is defined by Unreal for asserts
|
||||
#pragma push_macro("check")
|
||||
#undef check
|
||||
void check(Arena* arena);
|
||||
#pragma pop_macro("check")
|
||||
|
||||
struct Arena
|
||||
struct Arena_Def
|
||||
{
|
||||
AllocatorInfo Backing;
|
||||
void* PhysicalStart;
|
||||
@ -202,20 +201,20 @@ struct Arena
|
||||
|
||||
#if GEN_SUPPORT_CPP_MEMBER_FEATURES
|
||||
#pragma region Member Mapping
|
||||
forceinline operator AllocatorInfo() { return GEN_NS allocator_info(this); }
|
||||
forceinline operator AllocatorInfo() { return GEN_NS arena_allocator_info(this); }
|
||||
|
||||
forceinline static void* allocator_proc( void* allocator_data, AllocType type, ssize size, ssize alignment, void* old_memory, ssize old_size, u64 flags ) { return GEN_NS arena_allocator_proc( allocator_data, type, size, alignment, old_memory, old_size, flags ); }
|
||||
forceinline static Arena init_from_memory( void* start, ssize size ) { return GEN_NS arena_init_from_memory( start, size ); }
|
||||
forceinline static Arena init_from_allocator( AllocatorInfo backing, ssize size ) { return GEN_NS arena_init_from_allocator( backing, size ); }
|
||||
forceinline static Arena init_sub( Arena& parent, ssize size ) { return GEN_NS arena_init_from_allocator( parent.Backing, size ); }
|
||||
forceinline ssize alignment_of( ssize alignment ) { return GEN_NS alignment_of(this, alignment); }
|
||||
forceinline void free() { return GEN_NS free(this); }
|
||||
forceinline ssize size_remaining( ssize alignment ) { return GEN_NS size_remaining(this, alignment); }
|
||||
forceinline ssize alignment_of( ssize alignment ) { return GEN_NS arena_alignment_of(this, alignment); }
|
||||
forceinline void free() { return GEN_NS arena_free(this); }
|
||||
forceinline ssize size_remaining( ssize alignment ) { return GEN_NS arena_size_remaining(this, alignment); }
|
||||
|
||||
// This id is defined by Unreal for asserts
|
||||
#pragma push_macro("check")
|
||||
#undef check
|
||||
forceinline void check() { GEN_NS check(this); }
|
||||
forceinline void check() { GEN_NS arena_check(this); }
|
||||
#pragma pop_macro("check")
|
||||
|
||||
#pragma endregion Member Mapping
|
||||
@ -223,11 +222,11 @@ struct Arena
|
||||
};
|
||||
|
||||
#if GEN_SUPPORT_CPP_REFERENCES
|
||||
forceinline AllocatorInfo allocator_info(Arena& arena ) { return allocator_info(& arena); }
|
||||
forceinline Arena init_sub (Arena& parent, ssize size) { return init_sub( & parent, size); }
|
||||
forceinline ssize alignment_of (Arena& arena, ssize alignment) { return alignment_of( & arena, alignment); }
|
||||
forceinline void free (Arena& arena) { return free(& arena); }
|
||||
forceinline ssize size_remaining(Arena& arena, ssize alignment) { return size_remaining(& arena, alignment); }
|
||||
forceinline AllocatorInfo allocator_info(Arena& arena ) { return arena_allocator_info(& arena); }
|
||||
forceinline Arena init_sub (Arena& parent, ssize size) { return arena_init_sub( & parent, size); }
|
||||
forceinline ssize alignment_of (Arena& arena, ssize alignment) { return arena_alignment_of( & arena, alignment); }
|
||||
forceinline void free (Arena& arena) { return arena_free(& arena); }
|
||||
forceinline ssize size_remaining(Arena& arena, ssize alignment) { return arena_size_remaining(& arena, alignment); }
|
||||
|
||||
// This id is defined by Unreal for asserts
|
||||
#pragma push_macro("check")
|
||||
@ -238,9 +237,10 @@ forceinline void check(Arena& arena) { return check(& arena); };
|
||||
|
||||
|
||||
inline
|
||||
AllocatorInfo allocator_info( Arena* arena ) {
|
||||
AllocatorInfo arena_allocator_info( Arena* arena ) {
|
||||
GEN_ASSERT(arena != nullptr);
|
||||
return { arena_allocator_proc, arena };
|
||||
AllocatorInfo info = { arena_allocator_proc, arena };
|
||||
return info;
|
||||
}
|
||||
|
||||
inline
|
||||
@ -269,13 +269,13 @@ Arena arena_init_from_allocator(AllocatorInfo backing, ssize size) {
|
||||
}
|
||||
|
||||
inline
|
||||
Arena init_sub(Arena* parent, ssize size) {
|
||||
Arena arena_init_sub(Arena* parent, ssize size) {
|
||||
GEN_ASSERT(parent != nullptr);
|
||||
return arena_init_from_allocator(parent->Backing, size);
|
||||
}
|
||||
|
||||
inline
|
||||
ssize alignment_of(Arena* arena, ssize alignment)
|
||||
ssize arena_alignment_of(Arena* arena, ssize alignment)
|
||||
{
|
||||
GEN_ASSERT(arena != nullptr);
|
||||
ssize alignment_offset, result_pointer, mask;
|
||||
@ -291,36 +291,35 @@ ssize alignment_of(Arena* arena, ssize alignment)
|
||||
return alignment_offset;
|
||||
}
|
||||
|
||||
#pragma push_macro("check")
|
||||
#undef check
|
||||
inline
|
||||
void check(Arena* arena)
|
||||
void arena_check(Arena* arena)
|
||||
{
|
||||
GEN_ASSERT(arena != nullptr );
|
||||
GEN_ASSERT(arena->TempCount == 0);
|
||||
}
|
||||
#pragma pop_macro("check")
|
||||
|
||||
inline
|
||||
void free(Arena* arena)
|
||||
void arena_free(Arena* arena)
|
||||
{
|
||||
GEN_ASSERT(arena != nullptr);
|
||||
if (arena->Backing.Proc)
|
||||
{
|
||||
GEN_NS free(arena->Backing, arena->PhysicalStart);
|
||||
allocator_free(arena->Backing, arena->PhysicalStart);
|
||||
arena->PhysicalStart = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
inline
|
||||
ssize size_remaining(Arena* arena, ssize alignment)
|
||||
ssize arena_size_remaining(Arena* arena, ssize alignment)
|
||||
{
|
||||
GEN_ASSERT(arena != nullptr);
|
||||
ssize result = arena->TotalSize - (arena->TotalUsed + alignment_of(arena, alignment));
|
||||
ssize result = arena->TotalSize - (arena->TotalUsed + arena_alignment_of(arena, alignment));
|
||||
return result;
|
||||
}
|
||||
#pragma endregion Arena
|
||||
|
||||
GEN_API_C_END
|
||||
|
||||
#pragma region FixedArena
|
||||
template<s32 Size>
|
||||
struct FixedArena;
|
||||
@ -383,24 +382,27 @@ using Arena_2MB = FixedArena< megabytes( 2 ) >;
|
||||
using Arena_4MB = FixedArena< megabytes( 4 ) >;
|
||||
#pragma endregion FixedArena
|
||||
|
||||
GEN_API_C_BEGIN
|
||||
|
||||
#pragma region Pool
|
||||
struct Pool;
|
||||
struct Pool_Def;
|
||||
typedef struct Pool_Def Pool;
|
||||
|
||||
void* pool_allocator_proc(void* allocator_data, AllocType type, ssize size, ssize alignment, void* old_memory, ssize old_size, u64 flags);
|
||||
|
||||
Pool pool_init(AllocatorInfo backing, ssize num_blocks, ssize block_size);
|
||||
Pool pool_init_align(AllocatorInfo backing, ssize num_blocks, ssize block_size, ssize block_align);
|
||||
AllocatorInfo allocator_info(Pool* pool);
|
||||
void clear(Pool* pool);
|
||||
void free(Pool* pool);
|
||||
AllocatorInfo pool_allocator_info(Pool* pool);
|
||||
void pool_clear(Pool* pool);
|
||||
void pool_free(Pool* pool);
|
||||
|
||||
#if GEN_SUPPORT_CPP_REFERENCES
|
||||
AllocatorInfo allocator_info(Pool& pool);
|
||||
void clear(Pool& pool);
|
||||
void free(Pool& pool);
|
||||
AllocatorInfo allocator_info(Pool& pool) { return GEN_NS allocator_info(& pool); }
|
||||
void clear(Pool& pool) { return GEN_NS clear(& pool); }
|
||||
void free(Pool& pool) { return GEN_NS free(& pool); }
|
||||
#endif
|
||||
|
||||
struct Pool
|
||||
struct Pool_Def
|
||||
{
|
||||
AllocatorInfo Backing;
|
||||
void* PhysicalStart;
|
||||
@ -412,19 +414,19 @@ struct Pool
|
||||
|
||||
#if GEN_SUPPORT_CPP_MEMBER_FEATURES
|
||||
#pragma region Member Mapping
|
||||
forceinline operator AllocatorInfo() { return GEN_NS allocator_info(this); }
|
||||
forceinline operator AllocatorInfo() { return GEN_NS pool_allocator_info(this); }
|
||||
|
||||
forceinline static void* allocator_proc(void* allocator_data, AllocType type, ssize size, ssize alignment, void* old_memory, ssize old_size, u64 flags) { return GEN_NS pool_allocator_proc(allocator_data, type, size, alignment, old_memory, old_size, flags); }
|
||||
forceinline static Pool init(AllocatorInfo backing, ssize num_blocks, ssize block_size) { return GEN_NS pool_init(backing, num_blocks, block_size); }
|
||||
forceinline static Pool init_align(AllocatorInfo backing, ssize num_blocks, ssize block_size, ssize block_align) { return GEN_NS pool_init_align(backing, num_blocks, block_size, block_align); }
|
||||
forceinline void clear() { GEN_NS clear( this); }
|
||||
forceinline void free() { GEN_NS free( this); }
|
||||
forceinline void clear() { GEN_NS pool_clear( this); }
|
||||
forceinline void free() { GEN_NS pool_free( this); }
|
||||
#pragma endregion
|
||||
#endif
|
||||
};
|
||||
|
||||
inline
|
||||
AllocatorInfo allocator_info(Pool* pool) {
|
||||
AllocatorInfo pool_allocator_info(Pool* pool) {
|
||||
return { pool_allocator_proc, pool };
|
||||
}
|
||||
|
||||
@ -434,9 +436,9 @@ Pool pool_init(AllocatorInfo backing, ssize num_blocks, ssize block_size) {
|
||||
}
|
||||
|
||||
inline
|
||||
void free(Pool* pool) {
|
||||
void pool_free(Pool* pool) {
|
||||
if(pool->Backing.Proc) {
|
||||
GEN_NS free(pool->Backing, pool->PhysicalStart);
|
||||
allocator_free(pool->Backing, pool->PhysicalStart);
|
||||
}
|
||||
}
|
||||
#pragma endregion Pool
|
||||
@ -458,9 +460,9 @@ mem_ptr align_forward( void* ptr, ssize alignment )
|
||||
return to_mem_ptr(forward);
|
||||
}
|
||||
|
||||
inline s64 align_forward_i64( s64 value, ssize alignment ) { return value + ( alignment - value % alignment ) % alignment; }
|
||||
inline s64 align_forward_s64( s64 value, ssize alignment ) { return value + ( alignment - value % alignment ) % alignment; }
|
||||
|
||||
inline void* pointer_add ( void* ptr, ssize bytes ) { return rcast(void*, rcast( u8*, ptr) + bytes ); }
|
||||
inline void* pointer_add ( void* ptr, ssize bytes ) { return rcast(void*, rcast( u8*, ptr) + bytes ); }
|
||||
inline void const* pointer_add_const( void const* ptr, ssize bytes ) { return rcast(void const*, rcast( u8 const*, ptr) + bytes ); }
|
||||
|
||||
inline sptr pointer_diff( mem_ptr_const begin, mem_ptr_const end ) {
|
||||
@ -616,7 +618,7 @@ void* alloc( AllocatorInfo a, ssize size ) {
|
||||
}
|
||||
|
||||
inline
|
||||
void free( AllocatorInfo a, void* ptr ) {
|
||||
void allocator_free( AllocatorInfo a, void* ptr ) {
|
||||
if ( ptr != nullptr )
|
||||
a.Proc( a.Data, EAllocation_FREE, 0, 0, ptr, 0, GEN_DEFAULT_ALLOCATOR_FLAGS );
|
||||
}
|
||||
@ -644,7 +646,7 @@ void* default_resize_align( AllocatorInfo a, void* old_memory, ssize old_size, s
|
||||
|
||||
if ( new_size == 0 )
|
||||
{
|
||||
free( a, old_memory );
|
||||
allocator_free( a, old_memory );
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@ -662,7 +664,7 @@ void* default_resize_align( AllocatorInfo a, void* old_memory, ssize old_size, s
|
||||
return nullptr;
|
||||
|
||||
mem_move( new_memory, old_memory, min( new_size, old_size ) );
|
||||
free( a, old_memory );
|
||||
allocator_free( a, old_memory );
|
||||
return new_memory;
|
||||
}
|
||||
}
|
||||
@ -672,4 +674,6 @@ void zero_size( void* ptr, ssize size ) {
|
||||
mem_set( ptr, 0, size );
|
||||
}
|
||||
|
||||
GEN_API_C_END
|
||||
|
||||
#pragma endregion Memory
|
||||
|
@ -36,12 +36,12 @@ u8 adt_destroy_branch( ADT_Node* node )
|
||||
GEN_ASSERT_NOT_NULL( node );
|
||||
if ( ( node->type == EADT_TYPE_OBJECT || node->type == EADT_TYPE_ARRAY ) && node->nodes )
|
||||
{
|
||||
for ( ssize i = 0; i < scast(ssize, num(node->nodes)); ++i )
|
||||
for ( ssize i = 0; i < scast(ssize, array_num(node->nodes)); ++i )
|
||||
{
|
||||
adt_destroy_branch( node->nodes + i );
|
||||
}
|
||||
|
||||
free(& node->nodes);
|
||||
array_free(& node->nodes);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@ -66,7 +66,7 @@ ADT_Node* adt_find( ADT_Node* node, char const* name, b32 deep_search )
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for ( ssize i = 0; i < scast(ssize, num(node->nodes)); i++ )
|
||||
for ( ssize i = 0; i < scast(ssize, array_num(node->nodes)); i++ )
|
||||
{
|
||||
if ( ! str_compare( node->nodes[ i ].name, name ) )
|
||||
{
|
||||
@ -76,7 +76,7 @@ ADT_Node* adt_find( ADT_Node* node, char const* name, b32 deep_search )
|
||||
|
||||
if ( deep_search )
|
||||
{
|
||||
for ( ssize i = 0; i < scast(ssize, num(node->nodes)); i++ )
|
||||
for ( ssize i = 0; i < scast(ssize, array_num(node->nodes)); i++ )
|
||||
{
|
||||
ADT_Node* res = adt_find( node->nodes + i, name, deep_search );
|
||||
|
||||
@ -132,7 +132,7 @@ internal ADT_Node* _adt_get_value( ADT_Node* node, char const* value )
|
||||
|
||||
internal ADT_Node* _adt_get_field( ADT_Node* node, char* name, char* value )
|
||||
{
|
||||
for ( ssize i = 0; i < scast(ssize, num(node->nodes)); i++ )
|
||||
for ( ssize i = 0; i < scast(ssize, array_num(node->nodes)); i++ )
|
||||
{
|
||||
if ( ! str_compare( node->nodes[ i ].name, name ) )
|
||||
{
|
||||
@ -207,7 +207,7 @@ ADT_Node* adt_query( ADT_Node* node, char const* uri )
|
||||
/* run a value comparison against any child that is an object node */
|
||||
else if ( node->type == EADT_TYPE_ARRAY )
|
||||
{
|
||||
for ( ssize i = 0; i < scast(ssize, num(node->nodes)); i++ )
|
||||
for ( ssize i = 0; i < scast(ssize, array_num(node->nodes)); i++ )
|
||||
{
|
||||
ADT_Node* child = &node->nodes[ i ];
|
||||
if ( child->type != EADT_TYPE_OBJECT )
|
||||
@ -225,7 +225,7 @@ ADT_Node* adt_query( ADT_Node* node, char const* uri )
|
||||
/* [value] */
|
||||
else
|
||||
{
|
||||
for ( ssize i = 0; i < scast(ssize, num(node->nodes)); i++ )
|
||||
for ( ssize i = 0; i < scast(ssize, array_num(node->nodes)); i++ )
|
||||
{
|
||||
ADT_Node* child = &node->nodes[ i ];
|
||||
if ( _adt_get_value( child, l_b2 ) )
|
||||
@ -257,7 +257,7 @@ ADT_Node* adt_query( ADT_Node* node, char const* uri )
|
||||
else
|
||||
{
|
||||
ssize idx = ( ssize )str_to_i64( buf, NULL, 10 );
|
||||
if ( idx >= 0 && idx < scast(ssize, num(node->nodes)) )
|
||||
if ( idx >= 0 && idx < scast(ssize, array_num(node->nodes)) )
|
||||
{
|
||||
found_node = &node->nodes[ idx ];
|
||||
|
||||
@ -282,12 +282,12 @@ ADT_Node* adt_alloc_at( ADT_Node* parent, ssize index )
|
||||
if ( ! parent->nodes )
|
||||
return NULL;
|
||||
|
||||
if ( index < 0 || index > scast(ssize, num(parent->nodes)) )
|
||||
if ( index < 0 || index > scast(ssize, array_num(parent->nodes)) )
|
||||
return NULL;
|
||||
|
||||
ADT_Node o = { 0 };
|
||||
o.parent = parent;
|
||||
if ( ! append_at( & parent->nodes, o, index ) )
|
||||
if ( ! array_append_at( & parent->nodes, o, index ) )
|
||||
return NULL;
|
||||
|
||||
ADT_Node* node = & parent->nodes[index];
|
||||
@ -304,7 +304,7 @@ ADT_Node* adt_alloc( ADT_Node* parent )
|
||||
if ( ! parent->nodes )
|
||||
return NULL;
|
||||
|
||||
return adt_alloc_at( parent, num(parent->nodes) );
|
||||
return adt_alloc_at( parent, array_num(parent->nodes) );
|
||||
}
|
||||
|
||||
b8 adt_set_obj( ADT_Node* obj, char const* name, AllocatorInfo backing )
|
||||
@ -358,7 +358,7 @@ ADT_Node* adt_move_node( ADT_Node* node, ADT_Node* new_parent )
|
||||
GEN_ASSERT_NOT_NULL( node );
|
||||
GEN_ASSERT_NOT_NULL( new_parent );
|
||||
GEN_ASSERT( new_parent->type == EADT_TYPE_ARRAY || new_parent->type == EADT_TYPE_OBJECT );
|
||||
return adt_move_node_at( node, new_parent, num(new_parent->nodes) );
|
||||
return adt_move_node_at( node, new_parent, array_num(new_parent->nodes) );
|
||||
}
|
||||
|
||||
void adt_swap_nodes( ADT_Node* node, ADT_Node* other_node )
|
||||
@ -382,7 +382,7 @@ void adt_remove_node( ADT_Node* node )
|
||||
GEN_ASSERT_NOT_NULL( node->parent );
|
||||
ADT_Node* parent = node->parent;
|
||||
ssize index = ( pointer_diff( parent->nodes, node ) / size_of( ADT_Node ) );
|
||||
remove_at( parent->nodes, index );
|
||||
array_remove_at( parent->nodes, index );
|
||||
}
|
||||
|
||||
ADT_Node* adt_append_obj( ADT_Node* parent, char const* name )
|
||||
@ -390,7 +390,7 @@ ADT_Node* adt_append_obj( ADT_Node* parent, char const* name )
|
||||
ADT_Node* o = adt_alloc( parent );
|
||||
if ( ! o )
|
||||
return NULL;
|
||||
if ( adt_set_obj( o, name, get_header(parent->nodes)->Allocator ) )
|
||||
if ( adt_set_obj( o, name, array_get_header(parent->nodes)->Allocator ) )
|
||||
{
|
||||
adt_remove_node( o );
|
||||
return NULL;
|
||||
@ -404,7 +404,7 @@ ADT_Node* adt_append_arr( ADT_Node* parent, char const* name )
|
||||
if ( ! o )
|
||||
return NULL;
|
||||
|
||||
ArrayHeader* node_header = get_header(parent->nodes);
|
||||
ArrayHeader* node_header = array_get_header(parent->nodes);
|
||||
if ( adt_set_arr( o, name, node_header->Allocator ) )
|
||||
{
|
||||
adt_remove_node( o );
|
||||
@ -510,7 +510,7 @@ char* adt_parse_number( ADT_Node* node, char* base_str )
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( ! str_compare( e, "0x", 2 ) || ! str_compare( e, "0X", 2 ) )
|
||||
if ( ! str_compare_len( e, "0x", 2 ) || ! str_compare_len( e, "0X", 2 ) )
|
||||
{
|
||||
node_props = EADT_PROPS_IS_HEX;
|
||||
}
|
||||
@ -949,12 +949,12 @@ u8 csv_parse_delimiter( CSV_Object* root, char* text, AllocatorInfo allocator, b
|
||||
}
|
||||
}
|
||||
|
||||
if ( columnIndex >= scast(ssize, num(root->nodes)) )
|
||||
if ( columnIndex >= scast(ssize, array_num(root->nodes)) )
|
||||
{
|
||||
adt_append_arr( root, NULL );
|
||||
}
|
||||
|
||||
append( & root->nodes[ columnIndex ].nodes, rowItem );
|
||||
array_append( & root->nodes[ columnIndex ].nodes, rowItem );
|
||||
|
||||
if ( delimiter == delim )
|
||||
{
|
||||
@ -982,7 +982,7 @@ u8 csv_parse_delimiter( CSV_Object* root, char* text, AllocatorInfo allocator, b
|
||||
}
|
||||
while ( *currentChar );
|
||||
|
||||
if (num( root->nodes) == 0 )
|
||||
if (array_num( root->nodes) == 0 )
|
||||
{
|
||||
GEN_CSV_ASSERT( "unexpected end of input. stream is empty." );
|
||||
error = ECSV_Error__UNEXPECTED_END_OF_INPUT;
|
||||
@ -992,12 +992,12 @@ u8 csv_parse_delimiter( CSV_Object* root, char* text, AllocatorInfo allocator, b
|
||||
/* consider first row as a header. */
|
||||
if ( has_header )
|
||||
{
|
||||
for ( ssize i = 0; i < scast(ssize, num(root->nodes)); i++ )
|
||||
for ( ssize i = 0; i < scast(ssize, array_num(root->nodes)); i++ )
|
||||
{
|
||||
CSV_Object* col = root->nodes + i;
|
||||
CSV_Object* hdr = col->nodes;
|
||||
col->name = hdr->string;
|
||||
remove_at(col->nodes, 0 );
|
||||
array_remove_at(col->nodes, 0 );
|
||||
}
|
||||
}
|
||||
|
||||
@ -1060,11 +1060,11 @@ void csv_write_delimiter( FileInfo* file, CSV_Object* obj, char delimiter )
|
||||
GEN_ASSERT_NOT_NULL( file );
|
||||
GEN_ASSERT_NOT_NULL( obj );
|
||||
GEN_ASSERT( obj->nodes );
|
||||
ssize cols = num(obj->nodes);
|
||||
ssize cols = array_num(obj->nodes);
|
||||
if ( cols == 0 )
|
||||
return;
|
||||
|
||||
ssize rows = num(obj->nodes[ 0 ].nodes);
|
||||
ssize rows = array_num(obj->nodes[ 0 ].nodes);
|
||||
if ( rows == 0 )
|
||||
return;
|
||||
|
||||
|
@ -106,12 +106,24 @@
|
||||
# define GEN_GCC_VERSION_CHECK(major,minor,patch) (0)
|
||||
#endif
|
||||
|
||||
#ifndef GEN_COMPILER_C
|
||||
# if defined(__STDC_VERSION__)
|
||||
# define GEN_COMPILER_C 1
|
||||
#if !defined(GEN_COMPILER_C)
|
||||
# ifdef __cplusplus
|
||||
# define GEN_COMPILER_C 0
|
||||
# define GEN_COMPILER_CPP 1
|
||||
# else
|
||||
# define GEN_COMPILER_C 0
|
||||
# endif
|
||||
# if defined(__STDC__)
|
||||
# define GEN_COMPILER_C 1
|
||||
# define GEN_COMPILER_CPP 0
|
||||
# else
|
||||
// Fallback for very old C compilers
|
||||
# define GEN_COMPILER_C 1
|
||||
# define GEN_COMPILER_CPP 0
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if GEN_COMPILER_C
|
||||
#pragma message("Detected C")
|
||||
#endif
|
||||
|
||||
#pragma endregion Platform Detection
|
||||
@ -136,8 +148,6 @@
|
||||
# define GEN_NS_PARSER_BEGIN
|
||||
# define GEN_NS_PARSER_END
|
||||
# define GEN_USING_NS_PARSER
|
||||
# define GEN_NS_ENUM_BEGIN
|
||||
# define GEN_NS_ENUM_END
|
||||
# define GEN_NS
|
||||
# define GEN_NS_BEGIN
|
||||
# define GEN_NS_END
|
||||
@ -145,8 +155,6 @@
|
||||
# define GEN_NS_PARSER_BEGIN namespace parser {
|
||||
# define GEN_NS_PARSER_END }
|
||||
# define GEN_USING_NS_PARSER using namespace parser
|
||||
# define GEN_NS_ENUM_BEGIN namespace gen_internal_enums {
|
||||
# define GEN_NS_ENUM_END }
|
||||
# define GEN_NS ::
|
||||
# define GEN_NS_BEGIN
|
||||
# define GEN_NS_END
|
||||
@ -155,8 +163,6 @@
|
||||
# define GEN_NS_PARSER_BEGIN namespace parser {
|
||||
# define GEN_NS_PARSER_END }
|
||||
# define GEN_USING_NS_PARSER using namespace parser
|
||||
# define GEN_NS_ENUM_BEGIN namespace gen_internal_enums {
|
||||
# define GEN_NS_ENUM_END }
|
||||
# define GEN_NS gen::
|
||||
# define GEN_NS_BEGIN namespace gen {
|
||||
# define GEN_NS_END }
|
||||
|
@ -431,7 +431,7 @@ neverinline ssize str_fmt_va( char* text, ssize max_len, char const* fmt, va_lis
|
||||
|
||||
String gen_str = String { va_arg( va, char*) };
|
||||
|
||||
info.precision = length(gen_str);
|
||||
info.precision = string_length(gen_str);
|
||||
len = _print_string( text, remaining, &info, gen_str );
|
||||
}
|
||||
break;
|
||||
|
@ -5,6 +5,8 @@
|
||||
|
||||
#pragma region Printing
|
||||
|
||||
GEN_API_C_BEGIN
|
||||
|
||||
struct FileInfo;
|
||||
|
||||
#ifndef GEN_PRINTF_MAXLEN
|
||||
@ -38,4 +40,6 @@ ssize log_fmt(char const* fmt, ...)
|
||||
return res;
|
||||
}
|
||||
|
||||
GEN_API_C_END
|
||||
|
||||
#pragma endregion Printing
|
||||
|
@ -19,7 +19,7 @@ ssize _scan_zpl_i64( const char* text, s32 base, s64* value )
|
||||
text++;
|
||||
}
|
||||
|
||||
if ( base == 16 && str_compare( text, "0x", 2 ) == 0 )
|
||||
if ( base == 16 && str_compare_len( text, "0x", 2 ) == 0 )
|
||||
text += 2;
|
||||
|
||||
for ( ;; )
|
||||
@ -61,7 +61,7 @@ s64 str_to_i64( const char* str, char** end_ptr, s32 base )
|
||||
|
||||
if ( ! base )
|
||||
{
|
||||
if ( ( str_len( str ) > 2 ) && ( str_compare( str, "0x", 2 ) == 0 ) )
|
||||
if ( ( str_len( str ) > 2 ) && ( str_compare_len( str, "0x", 2 ) == 0 ) )
|
||||
base = 16;
|
||||
else
|
||||
base = 10;
|
||||
|
@ -5,6 +5,8 @@
|
||||
|
||||
#pragma region String Ops
|
||||
|
||||
GEN_API_C_BEGIN
|
||||
|
||||
const char* char_first_occurence( const char* str, char c );
|
||||
|
||||
b32 char_is_alpha( char c );
|
||||
@ -19,11 +21,11 @@ s32 digit_to_int( char c );
|
||||
s32 hex_digit_to_int( char c );
|
||||
|
||||
s32 str_compare( const char* s1, const char* s2 );
|
||||
s32 str_compare( const char* s1, const char* s2, ssize len );
|
||||
s32 str_compare_len( const char* s1, const char* s2, ssize len );
|
||||
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 );
|
||||
ssize str_len( const char* str, ssize max_len );
|
||||
ssize str_len_capped( const char* str, ssize max_len );
|
||||
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 );
|
||||
@ -132,7 +134,7 @@ s32 str_compare( const char* s1, const char* s2 )
|
||||
}
|
||||
|
||||
inline
|
||||
s32 str_compare( const char* s1, const char* s2, ssize len )
|
||||
s32 str_compare_len( const char* s1, const char* s2, ssize len )
|
||||
{
|
||||
for ( ; len > 0; s1++, s2++, len-- )
|
||||
{
|
||||
@ -204,7 +206,7 @@ ssize str_len( const char* str )
|
||||
}
|
||||
|
||||
inline
|
||||
ssize str_len( const char* str, ssize max_len )
|
||||
ssize str_len_capped( const char* str, ssize max_len )
|
||||
{
|
||||
const char* end = rcast(const char*, mem_find( str, 0, max_len ));
|
||||
if ( end )
|
||||
@ -240,7 +242,7 @@ char const* str_skip( char const* str, char c )
|
||||
inline
|
||||
char const* str_skip_any( char const* str, char const* char_list )
|
||||
{
|
||||
char const* closest_ptr = rcast( char const*, pointer_add_const( rcast(void const*, str), str_len( str ) ));
|
||||
char const* closest_ptr = rcast( char const*, pointer_add_const( rcast(mem_ptr_const, str), str_len( str ) ));
|
||||
ssize char_list_count = str_len( char_list );
|
||||
for ( ssize i = 0; i < char_list_count; i++ )
|
||||
{
|
||||
@ -284,4 +286,6 @@ void str_to_upper( char* str )
|
||||
}
|
||||
}
|
||||
|
||||
GEN_API_C_END
|
||||
|
||||
#pragma endregion String Ops
|
||||
|
@ -5,15 +5,19 @@
|
||||
|
||||
#pragma region Strings
|
||||
|
||||
GEN_API_C_BEGIN
|
||||
|
||||
struct StrC;
|
||||
|
||||
bool are_equal (StrC lhs, StrC rhs);
|
||||
char const* back (StrC str);
|
||||
bool contains (StrC str, StrC substring);
|
||||
StrC duplicate (StrC str, AllocatorInfo allocator);
|
||||
b32 starts_with (StrC str, StrC substring);
|
||||
StrC to_str (char const* bad_string);
|
||||
StrC visualize_whitespace(StrC str, AllocatorInfo allocator);
|
||||
bool strc_are_equal (StrC lhs, StrC rhs);
|
||||
char const* strc_back (StrC str);
|
||||
bool strc_contains (StrC str, StrC substring);
|
||||
StrC strc_duplicate (StrC str, AllocatorInfo allocator);
|
||||
b32 strc_starts_with (StrC str, StrC substring);
|
||||
StrC strc_to_str (char const* bad_string);
|
||||
StrC strc_visualize_whitespace(StrC str, AllocatorInfo allocator);
|
||||
|
||||
GEN_API_C_END
|
||||
|
||||
// Constant string with length.
|
||||
struct StrC
|
||||
@ -21,17 +25,17 @@ struct StrC
|
||||
ssize Len;
|
||||
char const* Ptr;
|
||||
|
||||
#if ! GEN_COMPILER_C
|
||||
operator char const* () const { return Ptr; }
|
||||
char const& operator[]( ssize index ) const { return Ptr[index]; }
|
||||
#if GEN_COMPILER_CPP
|
||||
forceinline operator char const* () const { return Ptr; }
|
||||
forceinline char const& operator[]( ssize index ) const { return Ptr[index]; }
|
||||
|
||||
#if GEN_SUPPORT_CPP_MEMBER_FEATURES
|
||||
bool is_equal (StrC rhs) const { return GEN_NS are_equal(* this, rhs); }
|
||||
char const* back () const { return GEN_NS back(* this); }
|
||||
bool contains (StrC substring) const { return GEN_NS contains(* this, substring); }
|
||||
StrC duplicate (AllocatorInfo allocator) const { return GEN_NS duplicate(* this, allocator); }
|
||||
b32 starts_with (StrC substring) const { return GEN_NS starts_with(* this, substring); }
|
||||
StrC visualize_whitespace(AllocatorInfo allocator) const { return GEN_NS visualize_whitespace(* this, allocator); }
|
||||
forceinline bool is_equal (StrC rhs) const { return GEN_NS strc_are_equal(* this, rhs); }
|
||||
forceinline char const* back () const { return GEN_NS strc_back(* this); }
|
||||
forceinline bool contains (StrC substring) const { return GEN_NS strc_contains(* this, substring); }
|
||||
forceinline StrC duplicate (AllocatorInfo allocator) const { return GEN_NS strc_duplicate(* this, allocator); }
|
||||
forceinline b32 starts_with (StrC substring) const { return GEN_NS strc_starts_with(* this, substring); }
|
||||
forceinline StrC visualize_whitespace(AllocatorInfo allocator) const { return GEN_NS strc_visualize_whitespace(* this, allocator); }
|
||||
#endif
|
||||
#endif
|
||||
};
|
||||
@ -39,12 +43,21 @@ struct StrC
|
||||
#define cast_to_strc( str ) * rcast( StrC*, (str) - sizeof(ssize) )
|
||||
#define txt( text ) StrC { sizeof( text ) - 1, ( text ) }
|
||||
|
||||
inline char const* begin(StrC str) { return str.Ptr; }
|
||||
inline char const* end (StrC str) { return str.Ptr + str.Len; }
|
||||
inline char const* next (StrC str, char const* iter) { return iter + 1; }
|
||||
GEN_API_C_BEGIN
|
||||
forceinline char const* strc_begin(StrC str) { return str.Ptr; }
|
||||
forceinline char const* strc_end (StrC str) { return str.Ptr + str.Len; }
|
||||
forceinline char const* strc_next (StrC str, char const* iter) { return iter + 1; }
|
||||
GEN_API_C_END
|
||||
|
||||
#if GEN_COMPILER_CPP && 0
|
||||
forceinline char const* begin(StrC str) { return str.Ptr; }
|
||||
forceinline char const* end (StrC str) { return str.Ptr + str.Len; }
|
||||
forceinline char const* next (StrC str, char const* iter) { return iter + 1; }
|
||||
#endif
|
||||
|
||||
GEN_API_C_BEGIN
|
||||
inline
|
||||
bool are_equal(StrC lhs, StrC rhs)
|
||||
bool strc_are_equal(StrC lhs, StrC rhs)
|
||||
{
|
||||
if (lhs.Len != rhs.Len)
|
||||
return false;
|
||||
@ -57,12 +70,12 @@ bool are_equal(StrC lhs, StrC rhs)
|
||||
}
|
||||
|
||||
inline
|
||||
char const* back(StrC str) {
|
||||
char const* strc_back(StrC str) {
|
||||
return & str.Ptr[str.Len - 1];
|
||||
}
|
||||
|
||||
inline
|
||||
bool contains(StrC str, StrC substring)
|
||||
bool strc_contains(StrC str, StrC substring)
|
||||
{
|
||||
if (substring.Len > str.Len)
|
||||
return false;
|
||||
@ -71,25 +84,26 @@ bool contains(StrC str, StrC substring)
|
||||
ssize sub_len = substring.Len;
|
||||
for (ssize idx = 0; idx <= main_len - sub_len; ++idx)
|
||||
{
|
||||
if (str_compare(str.Ptr + idx, substring.Ptr, sub_len) == 0)
|
||||
if (str_compare_len(str.Ptr + idx, substring.Ptr, sub_len) == 0)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
inline
|
||||
b32 starts_with(StrC str, StrC substring) {
|
||||
b32 strc_starts_with(StrC str, StrC substring) {
|
||||
if (substring.Len > str.Len)
|
||||
return false;
|
||||
|
||||
b32 result = str_compare(str.Ptr, substring.Ptr, substring.Len) == 0;
|
||||
b32 result = str_compare_len(str.Ptr, substring.Ptr, substring.Len) == 0;
|
||||
return result;
|
||||
}
|
||||
|
||||
inline
|
||||
StrC to_str( char const* bad_str ) {
|
||||
StrC to_strc_from_c_str( char const* bad_str ) {
|
||||
return { str_len( bad_str ), bad_str };
|
||||
}
|
||||
GEN_API_C_END
|
||||
|
||||
// Dynamic String
|
||||
// This is directly based off the ZPL string api.
|
||||
@ -104,42 +118,44 @@ typedef char* String;
|
||||
struct String;
|
||||
#endif
|
||||
|
||||
usize string_grow_formula(usize value);
|
||||
GEN_API_C_BEGIN
|
||||
forceinline usize string_grow_formula(usize value);
|
||||
|
||||
String string_make (AllocatorInfo allocator, char const* str);
|
||||
String string_make (AllocatorInfo allocator, StrC str);
|
||||
String string_make_reserve (AllocatorInfo allocator, ssize capacity);
|
||||
String string_make_length (AllocatorInfo allocator, char const* str, ssize length);
|
||||
String string_fmt (AllocatorInfo allocator, char* buf, ssize buf_size, char const* fmt, ...);
|
||||
String string_fmt_buf (AllocatorInfo allocator, char const* fmt, ...);
|
||||
String string_join (AllocatorInfo allocator, char const** parts, ssize num_parts, char const* glue);
|
||||
bool are_equal (String const lhs, String const rhs);
|
||||
bool are_equal (String const lhs, StrC rhs);
|
||||
bool make_space_for (String* str, char const* to_append, ssize add_len);
|
||||
bool append (String* str, char c);
|
||||
bool append (String* str, char const* str_to_append);
|
||||
bool append (String* str, char const* str_to_append, ssize length);
|
||||
bool append (String* str, StrC str_to_append);
|
||||
bool append (String* str, String const other);
|
||||
bool append_fmt (String* str, char const* fmt, ...);
|
||||
ssize avail_space (String const str);
|
||||
char* back (String str);
|
||||
bool contains (String const str, StrC substring);
|
||||
bool contains (String const str, String const substring);
|
||||
ssize capacity (String const str);
|
||||
void clear (String str);
|
||||
String duplicate (String const str, AllocatorInfo allocator);
|
||||
void free (String* str);
|
||||
StringHeader* get_header (String str);
|
||||
ssize length (String const str);
|
||||
b32 starts_with (String const str, StrC substring);
|
||||
b32 starts_with (String const str, String substring);
|
||||
void skip_line (String str);
|
||||
void strip_space (String str);
|
||||
StrC to_strc (String str);
|
||||
void trim (String str, char const* cut_set);
|
||||
void trim_space (String str);
|
||||
String visualize_whitespace(String const str);
|
||||
String string_make_c_str (AllocatorInfo allocator, char const* str);
|
||||
String string_make_strc (AllocatorInfo allocator, StrC str);
|
||||
String string_make_reserve (AllocatorInfo allocator, ssize capacity);
|
||||
String string_make_length (AllocatorInfo allocator, char const* str, ssize length);
|
||||
String string_fmt (AllocatorInfo allocator, char* buf, ssize buf_size, char const* fmt, ...);
|
||||
String string_fmt_buf (AllocatorInfo allocator, char const* fmt, ...);
|
||||
String string_join (AllocatorInfo allocator, char const** parts, ssize num_parts, char const* glue);
|
||||
bool string_are_equal (String const lhs, String const rhs);
|
||||
bool string_are_equal_strc (String const lhs, StrC rhs);
|
||||
bool string_make_space_for (String* str, char const* to_append, ssize add_len);
|
||||
bool string_append_char (String* str, char c);
|
||||
bool string_append_c_str (String* str, char const* str_to_append);
|
||||
bool string_append_c_str_len (String* str, char const* str_to_append, ssize length);
|
||||
bool string_append_strc (String* str, StrC str_to_append);
|
||||
bool string_append_string (String* str, String const other);
|
||||
bool string_append_fmt (String* str, char const* fmt, ...);
|
||||
ssize string_avail_space (String const str);
|
||||
char* string_back (String str);
|
||||
bool string_contains_strc (String const str, StrC substring);
|
||||
bool string_contains_string (String const str, String const substring);
|
||||
ssize string_capacity (String const str);
|
||||
void string_clear (String str);
|
||||
String string_duplicate (String const str, AllocatorInfo allocator);
|
||||
void string_free (String* str);
|
||||
StringHeader* string_get_header (String str);
|
||||
ssize string_length (String const str);
|
||||
b32 string_starts_with_strc (String const str, StrC substring);
|
||||
b32 string_starts_with_string (String const str, String substring);
|
||||
void string_skip_line (String str);
|
||||
void string_strip_space (String str);
|
||||
StrC string_to_strc (String str);
|
||||
void string_trim (String str, char const* cut_set);
|
||||
void string_trim_space (String str);
|
||||
String string_visualize_whitespace(String const str);
|
||||
GEN_API_C_END
|
||||
|
||||
struct StringHeader {
|
||||
AllocatorInfo Allocator;
|
||||
@ -147,7 +163,7 @@ struct StringHeader {
|
||||
ssize Length;
|
||||
};
|
||||
|
||||
#if ! GEN_COMPILER_C && GEN_SUPPORT_CPP_MEMBER_FEATURES
|
||||
#if GEN_COMPILER_CPP && GEN_SUPPORT_CPP_MEMBER_FEATURES
|
||||
struct String
|
||||
{
|
||||
char* Data;
|
||||
@ -169,10 +185,10 @@ struct String
|
||||
forceinline char& operator[](ssize index) { return Data[index]; }
|
||||
forceinline char const& operator[](ssize index) const { return Data[index]; }
|
||||
|
||||
bool operator==(std::nullptr_t) const { return Data == nullptr; }
|
||||
bool operator!=(std::nullptr_t) const { return Data != nullptr; }
|
||||
friend bool operator==(std::nullptr_t, const String str) { return str.Data == nullptr; }
|
||||
friend bool operator!=(std::nullptr_t, const String str) { return str.Data != nullptr; }
|
||||
forceinline bool operator==(std::nullptr_t) const { return Data == nullptr; }
|
||||
forceinline bool operator!=(std::nullptr_t) const { return Data != nullptr; }
|
||||
friend forceinline bool operator==(std::nullptr_t, const String str) { return str.Data == nullptr; }
|
||||
friend forceinline bool operator!=(std::nullptr_t, const String str) { return str.Data != nullptr; }
|
||||
|
||||
forceinline char* begin() const { return Data; }
|
||||
forceinline char* end() const { return Data + GEN_NS length(* this); }
|
||||
@ -206,29 +222,29 @@ struct String
|
||||
}
|
||||
|
||||
forceinline bool make_space_for(char const* str, ssize add_len) { return GEN_NS make_space_for(this, str, add_len); }
|
||||
forceinline bool append(char c) { return GEN_NS append(this, c); }
|
||||
forceinline bool append(char const* str) { return GEN_NS append(this, str); }
|
||||
forceinline bool append(char const* str, ssize length) { return GEN_NS append(this, str, length); }
|
||||
forceinline bool append(StrC str) { return GEN_NS append(this, str); }
|
||||
forceinline bool append(const String other) { return GEN_NS append(this, other); }
|
||||
forceinline ssize avail_space() const { return GEN_NS avail_space(* this); }
|
||||
forceinline char* back() { return GEN_NS back(* this); }
|
||||
forceinline bool contains(StrC substring) const { return GEN_NS contains(* this, substring); }
|
||||
forceinline bool contains(String const& substring) const { return GEN_NS contains(* this, substring); }
|
||||
forceinline bool append(char c) { return GEN_NS string_append_char(this, c); }
|
||||
forceinline bool append(char const* str) { return GEN_NS string_append_c_str(this, str); }
|
||||
forceinline bool append(char const* str, ssize length) { return GEN_NS string_append_c_str_len(this, str, length); }
|
||||
forceinline bool append(StrC str) { return GEN_NS string_append_strc(this, str); }
|
||||
forceinline bool append(const String other) { return GEN_NS string_append_string(this, other); }
|
||||
forceinline ssize avail_space() const { return GEN_NS string_avail_space(* this); }
|
||||
forceinline char* back() { return GEN_NS string_back(* this); }
|
||||
forceinline bool contains(StrC substring) const { return GEN_NS string_contains_strc(* this, substring); }
|
||||
forceinline bool contains(String const& substring) const { return GEN_NS string_contains_string(* this, substring); }
|
||||
forceinline ssize capacity() const { return GEN_NS capacity(* this); }
|
||||
forceinline void clear() { GEN_NS clear(* this); }
|
||||
forceinline void clear() { GEN_NS clear(* this); }
|
||||
forceinline String duplicate(AllocatorInfo allocator) const { return GEN_NS duplicate(* this, allocator); }
|
||||
forceinline void free() { GEN_NS free(this); }
|
||||
forceinline void free() { GEN_NS free(this); }
|
||||
forceinline bool is_equal(String const& other) const { return GEN_NS are_equal(* this, other); }
|
||||
forceinline bool is_equal(StrC other) const { return GEN_NS are_equal(* this, other); }
|
||||
forceinline ssize length() const { return GEN_NS length(* this); }
|
||||
forceinline b32 starts_with(StrC substring) const { return GEN_NS starts_with(* this, substring); }
|
||||
forceinline b32 starts_with(String substring) const { return GEN_NS starts_with(* this, substring); }
|
||||
forceinline void skip_line() { GEN_NS skip_line(* this); }
|
||||
forceinline void strip_space() { GEN_NS strip_space(* this); }
|
||||
forceinline void skip_line() { GEN_NS skip_line(* this); }
|
||||
forceinline void strip_space() { GEN_NS strip_space(* this); }
|
||||
forceinline StrC to_strc() { return { length(), Data}; }
|
||||
forceinline void trim(char const* cut_set) { GEN_NS trim(* this, cut_set); }
|
||||
forceinline void trim_space() { GEN_NS trim_space(* this); }
|
||||
forceinline void trim(char const* cut_set) { GEN_NS trim(* this, cut_set); }
|
||||
forceinline void trim_space() { GEN_NS trim_space(* this); }
|
||||
forceinline String visualize_whitespace() const { return GEN_NS visualize_whitespace(* this); }
|
||||
forceinline StringHeader& get_header() { return * GEN_NS get_header(* this); }
|
||||
|
||||
@ -247,37 +263,47 @@ struct String
|
||||
};
|
||||
#endif
|
||||
|
||||
inline char* begin(String str) { return ((char*) str); }
|
||||
inline char* end (String str) { return ((char*) str + length(str)); }
|
||||
inline char* next (String str, char* iter) { return ((char*) iter + 1); }
|
||||
GEN_API_C_BEGIN
|
||||
forceinline char* string_begin(String str) { return ((char*) str); }
|
||||
forceinline char* string_end (String str) { return ((char*) str + string_length(str)); }
|
||||
forceinline char* string_next (String str, char const* iter) { return ((char*) iter + 1); }
|
||||
GEN_API_C_END
|
||||
|
||||
#if GEN_SUPPORT_CPP_REFERENCES
|
||||
inline bool make_space_for(String& str, char const* to_append, ssize add_len);
|
||||
inline bool append(String& str, char c);
|
||||
inline bool append(String& str, char const* str_to_append);
|
||||
inline bool append(String& str, char const* str_to_append, ssize length);
|
||||
inline bool append(String& str, StrC str_to_append);
|
||||
inline bool append(String& str, const String other);
|
||||
inline bool append_fmt(String& str, char const* fmt, ...);
|
||||
inline char& back(String& str);
|
||||
inline void clear(String& str);
|
||||
inline void free(String& str);
|
||||
#if GEN_COMPILER_CPP && 0
|
||||
forceinline char* begin(String str) { return ((char*) str); }
|
||||
forceinline char* end (String str) { return ((char*) str + string_length(str)); }
|
||||
forceinline char* next (String str, char* iter) { return ((char*) iter + 1); }
|
||||
#endif
|
||||
|
||||
inline
|
||||
#if GEN_SUPPORT_CPP_REFERENCES
|
||||
forceinline bool make_space_for(String& str, char const* to_append, ssize add_len);
|
||||
forceinline bool append(String& str, char c);
|
||||
forceinline bool append(String& str, char const* str_to_append);
|
||||
forceinline bool append(String& str, char const* str_to_append, ssize length);
|
||||
forceinline bool append(String& str, StrC str_to_append);
|
||||
forceinline bool append(String& str, const String other);
|
||||
forceinline bool append_fmt(String& str, char const* fmt, ...);
|
||||
forceinline char& back(String& str);
|
||||
forceinline void clear(String& str);
|
||||
forceinline void free(String& str);
|
||||
#endif
|
||||
|
||||
GEN_API_C_BEGIN
|
||||
|
||||
forceinline
|
||||
usize string_grow_formula(usize value) {
|
||||
// Using a very aggressive growth formula to reduce time mem_copying with recursive calls to append in this library.
|
||||
return 4 * value + 8;
|
||||
}
|
||||
|
||||
inline
|
||||
String string_make(AllocatorInfo allocator, char const* str) {
|
||||
forceinline
|
||||
String string_make_c_str(AllocatorInfo allocator, char const* str) {
|
||||
ssize length = str ? str_len(str) : 0;
|
||||
return string_make_length(allocator, str, length);
|
||||
}
|
||||
|
||||
inline
|
||||
String string_make(AllocatorInfo allocator, StrC str) {
|
||||
forceinline
|
||||
String string_make_strc(AllocatorInfo allocator, StrC str) {
|
||||
return string_make_length(allocator, str.Ptr, str.Len);
|
||||
}
|
||||
|
||||
@ -285,10 +311,10 @@ inline
|
||||
String string_fmt(AllocatorInfo allocator, char* buf, ssize buf_size, char const* fmt, ...) {
|
||||
va_list va;
|
||||
va_start(va, fmt);
|
||||
str_fmt_va(buf, buf_size, fmt, va);
|
||||
ssize res = str_fmt_va(buf, buf_size, fmt, va);
|
||||
va_end(va);
|
||||
|
||||
return string_make(allocator, buf);
|
||||
return string_make_length(allocator, buf, res);
|
||||
}
|
||||
|
||||
inline
|
||||
@ -299,52 +325,52 @@ String string_fmt_buf(AllocatorInfo allocator, char const* fmt, ...)
|
||||
|
||||
va_list va;
|
||||
va_start(va, fmt);
|
||||
str_fmt_va(buf, GEN_PRINTF_MAXLEN, fmt, va);
|
||||
ssize res = str_fmt_va(buf, GEN_PRINTF_MAXLEN, fmt, va);
|
||||
va_end(va);
|
||||
|
||||
return string_make(allocator, buf);
|
||||
return string_make_length(allocator, buf, res);
|
||||
}
|
||||
|
||||
inline
|
||||
String string_join(AllocatorInfo allocator, char const** parts, ssize num_parts, char const* glue)
|
||||
{
|
||||
String result = string_make(allocator, "");
|
||||
String result = string_make_c_str(allocator, "");
|
||||
|
||||
for (ssize idx = 0; idx < num_parts; ++idx)
|
||||
{
|
||||
append(& result, parts[idx]);
|
||||
string_append_c_str(& result, parts[idx]);
|
||||
|
||||
if (idx < num_parts - 1)
|
||||
append(& result, glue);
|
||||
string_append_c_str(& result, glue);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
inline
|
||||
bool append(String* str, char c) {
|
||||
forceinline
|
||||
bool string_append_char(String* str, char c) {
|
||||
GEN_ASSERT(str != nullptr);
|
||||
return append( str, (char const*)& c, (ssize)1);
|
||||
return string_append_c_str_len( str, (char const*)& c, (ssize)1);
|
||||
}
|
||||
|
||||
forceinline
|
||||
bool string_append_c_str(String* str, char const* str_to_append) {
|
||||
GEN_ASSERT(str != nullptr);
|
||||
return string_append_c_str_len(str, str_to_append, str_len(str_to_append));
|
||||
}
|
||||
|
||||
inline
|
||||
bool append(String* str, char const* str_to_append) {
|
||||
GEN_ASSERT(str != nullptr);
|
||||
return append(str, str_to_append, str_len(str_to_append));
|
||||
}
|
||||
|
||||
inline
|
||||
bool append(String* str, char const* str_to_append, ssize append_length)
|
||||
bool string_append_str_c_len(String* str, char const* str_to_append, ssize append_length)
|
||||
{
|
||||
GEN_ASSERT(str != nullptr);
|
||||
if (sptr(str_to_append) > 0)
|
||||
{
|
||||
ssize curr_len = length(* str);
|
||||
ssize curr_len = string_length(* str);
|
||||
|
||||
if ( ! make_space_for(str, str_to_append, append_length))
|
||||
if ( ! string_make_space_for(str, str_to_append, append_length))
|
||||
return false;
|
||||
|
||||
StringHeader* header = get_header(* str);
|
||||
StringHeader* header = string_get_header(* str);
|
||||
|
||||
char* Data = * str;
|
||||
mem_copy( Data + curr_len, str_to_append, append_length);
|
||||
@ -356,16 +382,16 @@ bool append(String* str, char const* str_to_append, ssize append_length)
|
||||
return str_to_append != nullptr;
|
||||
}
|
||||
|
||||
inline
|
||||
bool append(String* str, StrC str_to_append) {
|
||||
forceinline
|
||||
bool string_append_strc(String* str, StrC str_to_append) {
|
||||
GEN_ASSERT(str != nullptr);
|
||||
return append(str, str_to_append.Ptr, str_to_append.Len);
|
||||
return string_append_c_str_len(str, str_to_append.Ptr, str_to_append.Len);
|
||||
}
|
||||
|
||||
inline
|
||||
bool append(String* str, String const other) {
|
||||
forceinline
|
||||
bool string_append_string(String* str, String const other) {
|
||||
GEN_ASSERT(str != nullptr);
|
||||
return append(str, (char const*)other, length(other));
|
||||
return string_append_c_str_len(str, (char const*)other, string_length(other));
|
||||
}
|
||||
|
||||
bool append_fmt(String* str, char const* fmt, ...) {
|
||||
@ -378,16 +404,16 @@ bool append_fmt(String* str, char const* fmt, ...) {
|
||||
res = str_fmt_va(buf, count_of(buf) - 1, fmt, va) - 1;
|
||||
va_end(va);
|
||||
|
||||
return append(str, (char const*)buf, res);
|
||||
return string_append_c_str_len(str, (char const*)buf, res);
|
||||
}
|
||||
|
||||
inline
|
||||
bool are_equal(String const lhs, String const rhs)
|
||||
bool string_are_equal_string(String const lhs, String const rhs)
|
||||
{
|
||||
if (length(lhs) != length(rhs))
|
||||
if (string_length(lhs) != string_length(rhs))
|
||||
return false;
|
||||
|
||||
for (ssize idx = 0; idx < length(lhs); ++idx)
|
||||
for (ssize idx = 0; idx < string_length(lhs); ++idx)
|
||||
if (lhs[idx] != rhs[idx])
|
||||
return false;
|
||||
|
||||
@ -395,27 +421,27 @@ bool are_equal(String const lhs, String const rhs)
|
||||
}
|
||||
|
||||
inline
|
||||
bool are_equal(String const lhs, StrC rhs)
|
||||
bool string_are_equal_strc(String const lhs, StrC rhs)
|
||||
{
|
||||
if (length(lhs) != (rhs.Len))
|
||||
if (string_length(lhs) != (rhs.Len))
|
||||
return false;
|
||||
|
||||
for (ssize idx = 0; idx < length(lhs); ++idx)
|
||||
for (ssize idx = 0; idx < string_length(lhs); ++idx)
|
||||
if (lhs[idx] != rhs.Ptr[idx])
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
inline
|
||||
forceinline
|
||||
ssize avail_space(String const str) {
|
||||
StringHeader const* header = rcast(StringHeader const*, scast(char const*, str) - sizeof(StringHeader));
|
||||
return header->Capacity - header->Length;
|
||||
}
|
||||
|
||||
inline
|
||||
forceinline
|
||||
char* back(String* str) {
|
||||
return & (*str)[length(* str) - 1];
|
||||
return & (*str)[string_length(* str) - 1];
|
||||
}
|
||||
|
||||
inline
|
||||
@ -431,7 +457,7 @@ bool contains(String const str, StrC substring)
|
||||
|
||||
for (ssize idx = 0; idx <= main_len - sub_len; ++idx)
|
||||
{
|
||||
if (str_compare(str + idx, substring.Ptr, sub_len) == 0)
|
||||
if (str_compare_len(str + idx, substring.Ptr, sub_len) == 0)
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -439,67 +465,67 @@ bool contains(String const str, StrC substring)
|
||||
}
|
||||
|
||||
inline
|
||||
bool contains(String const str, String const substring)
|
||||
bool string_contains_string(String const str, String const substring)
|
||||
{
|
||||
StringHeader const* header = rcast(StringHeader const*, scast(char const*, str) - sizeof(StringHeader));
|
||||
|
||||
if (length(substring) > header->Length)
|
||||
if (string_length(substring) > header->Length)
|
||||
return false;
|
||||
|
||||
ssize main_len = header->Length;
|
||||
ssize sub_len = length(substring);
|
||||
ssize sub_len = string_length(substring);
|
||||
|
||||
for (ssize idx = 0; idx <= main_len - sub_len; ++idx)
|
||||
{
|
||||
if (str_compare(str + idx, substring, sub_len) == 0)
|
||||
if (str_compare_len(str + idx, substring, sub_len) == 0)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
inline
|
||||
ssize capacity(String const str) {
|
||||
forceinline
|
||||
ssize string_capacity(String const str) {
|
||||
StringHeader const* header = rcast(StringHeader const*, scast(char const*, str) - sizeof(StringHeader));
|
||||
return header->Capacity;
|
||||
}
|
||||
|
||||
inline
|
||||
void clear(String str) {
|
||||
get_header(str)->Length = 0;
|
||||
forceinline
|
||||
void string_clear(String str) {
|
||||
string_get_header(str)->Length = 0;
|
||||
}
|
||||
|
||||
inline
|
||||
String duplicate(String const str, AllocatorInfo allocator) {
|
||||
return string_make_length(allocator, str, length(str));
|
||||
forceinline
|
||||
String string_duplicate(String const str, AllocatorInfo allocator) {
|
||||
return string_make_length(allocator, str, string_length(str));
|
||||
}
|
||||
|
||||
inline
|
||||
void free(String* str) {
|
||||
forceinline
|
||||
void string_free(String* str) {
|
||||
GEN_ASSERT(str != nullptr);
|
||||
if (! (* str))
|
||||
return;
|
||||
|
||||
StringHeader* header = get_header(* str);
|
||||
GEN_NS free(header->Allocator, header);
|
||||
StringHeader* header = string_get_header(* str);
|
||||
allocator_free(header->Allocator, header);
|
||||
}
|
||||
|
||||
inline
|
||||
StringHeader* get_header(String str) {
|
||||
forceinline
|
||||
StringHeader* string_get_header(String str) {
|
||||
return (StringHeader*)(scast(char*, str) - sizeof(StringHeader));
|
||||
}
|
||||
|
||||
inline
|
||||
ssize length(String const str)
|
||||
forceinline
|
||||
ssize string_length(String const str)
|
||||
{
|
||||
StringHeader const& header = *rcast(StringHeader const*, scast(char const*, str) - sizeof(StringHeader));
|
||||
return header.Length;
|
||||
}
|
||||
|
||||
inline
|
||||
bool make_space_for(String* str, char const* to_append, ssize add_len)
|
||||
bool string_make_space_for(String* str, char const* to_append, ssize add_len)
|
||||
{
|
||||
ssize available = avail_space(* str);
|
||||
ssize available = string_avail_space(* str);
|
||||
|
||||
if (available >= add_len) {
|
||||
return true;
|
||||
@ -510,12 +536,12 @@ bool make_space_for(String* str, char const* to_append, ssize add_len)
|
||||
void* ptr;
|
||||
void* new_ptr;
|
||||
|
||||
AllocatorInfo allocator = get_header(* str)->Allocator;
|
||||
AllocatorInfo allocator = string_get_header(* str)->Allocator;
|
||||
StringHeader* header = nullptr;
|
||||
|
||||
new_len = string_grow_formula(length(* str) + add_len);
|
||||
ptr = get_header(* str);
|
||||
old_size = size_of(StringHeader) + length(* str) + 1;
|
||||
new_len = string_grow_formula(string_length(* str) + add_len);
|
||||
ptr = string_get_header(* str);
|
||||
old_size = size_of(StringHeader) + string_length(* str) + 1;
|
||||
new_size = size_of(StringHeader) + new_len + 1;
|
||||
|
||||
new_ptr = resize(allocator, ptr, old_size, new_size);
|
||||
@ -534,26 +560,26 @@ bool make_space_for(String* str, char const* to_append, ssize add_len)
|
||||
}
|
||||
}
|
||||
|
||||
inline
|
||||
b32 starts_with(String const str, StrC substring) {
|
||||
if (substring.Len > length(str))
|
||||
forceinline
|
||||
b32 string_starts_with_strc(String const str, StrC substring) {
|
||||
if (substring.Len > string_length(str))
|
||||
return false;
|
||||
|
||||
b32 result = str_compare(str, substring.Ptr, substring.Len) == 0;
|
||||
b32 result = str_compare_len(str, substring.Ptr, substring.Len) == 0;
|
||||
return result;
|
||||
}
|
||||
|
||||
inline
|
||||
b32 starts_with(String const str, String substring) {
|
||||
if (length(substring) > length(str))
|
||||
forceinline
|
||||
b32 string_starts_with_string(String const str, String substring) {
|
||||
if (string_length(substring) > string_length(str))
|
||||
return false;
|
||||
|
||||
b32 result = str_compare(str, substring, length(substring) - 1) == 0;
|
||||
b32 result = str_compare_len(str, substring, string_length(substring) - 1) == 0;
|
||||
return result;
|
||||
}
|
||||
|
||||
inline
|
||||
void skip_line(String str)
|
||||
void string_skip_line(String str)
|
||||
{
|
||||
#define current (*scanner)
|
||||
char* scanner = str;
|
||||
@ -569,7 +595,7 @@ void skip_line(String str)
|
||||
|
||||
mem_move((char*)str, scanner, new_length);
|
||||
|
||||
StringHeader* header = get_header(str);
|
||||
StringHeader* header = string_get_header(str);
|
||||
header->Length = new_length;
|
||||
#undef current
|
||||
}
|
||||
@ -593,12 +619,12 @@ void strip_space(String str)
|
||||
write_pos[0] = '\0'; // Null-terminate the modified string
|
||||
|
||||
// Update the length if needed
|
||||
get_header(str)->Length = write_pos - str;
|
||||
string_get_header(str)->Length = write_pos - str;
|
||||
}
|
||||
|
||||
inline
|
||||
StrC to_strc(String str) {
|
||||
return { length(str), (char const*)str };
|
||||
forceinline
|
||||
StrC string_to_strc(String str) {
|
||||
return { string_length(str), (char const*)str };
|
||||
}
|
||||
|
||||
inline
|
||||
@ -607,7 +633,7 @@ void trim(String str, char const* cut_set)
|
||||
ssize len = 0;
|
||||
|
||||
char* start_pos = str;
|
||||
char* end_pos = scast(char*, str) + length(str) - 1;
|
||||
char* end_pos = scast(char*, str) + string_length(str) - 1;
|
||||
|
||||
while (start_pos <= end_pos && char_first_occurence(cut_set, *start_pos))
|
||||
start_pos++;
|
||||
@ -622,10 +648,10 @@ void trim(String str, char const* cut_set)
|
||||
|
||||
str[len] = '\0';
|
||||
|
||||
get_header(str)->Length = len;
|
||||
string_get_header(str)->Length = len;
|
||||
}
|
||||
|
||||
inline
|
||||
forceinline
|
||||
void trim_space(String str) {
|
||||
trim(str, " \t\r\n\v\f");
|
||||
}
|
||||
@ -634,30 +660,31 @@ inline
|
||||
String visualize_whitespace(String const str)
|
||||
{
|
||||
StringHeader* header = (StringHeader*)(scast(char const*, str) - sizeof(StringHeader));
|
||||
String result = string_make_reserve(header->Allocator, length(str) * 2); // Assume worst case for space requirements.
|
||||
String result = string_make_reserve(header->Allocator, string_length(str) * 2); // Assume worst case for space requirements.
|
||||
|
||||
foreach (char*, c, str) switch ( * c )
|
||||
for (char const* c = string_begin(str); c != string_end(str); c = string_next(str, c))
|
||||
switch ( * c )
|
||||
{
|
||||
case ' ':
|
||||
append(& result, txt("·"));
|
||||
string_append_strc(& result, txt("·"));
|
||||
break;
|
||||
case '\t':
|
||||
append(& result, txt("→"));
|
||||
string_append_strc(& result, txt("→"));
|
||||
break;
|
||||
case '\n':
|
||||
append(& result, txt("↵"));
|
||||
string_append_strc(& result, txt("↵"));
|
||||
break;
|
||||
case '\r':
|
||||
append(& result, txt("⏎"));
|
||||
string_append_strc(& result, txt("⏎"));
|
||||
break;
|
||||
case '\v':
|
||||
append(& result, txt("⇕"));
|
||||
string_append_strc(& result, txt("⇕"));
|
||||
break;
|
||||
case '\f':
|
||||
append(& result, txt("⌂"));
|
||||
string_append_strc(& result, txt("⌂"));
|
||||
break;
|
||||
default:
|
||||
append(& result, c);
|
||||
string_append_char(& result, * c);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -670,47 +697,50 @@ struct String_POD {
|
||||
};
|
||||
static_assert( sizeof( String_POD ) == sizeof( String ), "String is not a POD" );
|
||||
|
||||
inline
|
||||
StrC duplicate(StrC str, AllocatorInfo allocator) {
|
||||
forceinline
|
||||
StrC strc_duplicate(StrC str, AllocatorInfo allocator) {
|
||||
String result = string_make_length(allocator, str.Ptr, str.Len);
|
||||
return { get_header(result)->Length, result };
|
||||
return { string_get_header(result)->Length, result };
|
||||
}
|
||||
|
||||
inline
|
||||
StrC visualize_whitespace(StrC str, AllocatorInfo allocator)
|
||||
StrC strc_visualize_whitespace(StrC str, AllocatorInfo allocator)
|
||||
{
|
||||
String result = string_make_reserve(allocator, str.Len * 2); // Assume worst case for space requirements.
|
||||
foreach (char const*, c, str) switch ( * c )
|
||||
for (char const* c = strc_begin(str); c != strc_end(str); c = strc_next(str, c))
|
||||
switch ( * c )
|
||||
{
|
||||
case ' ':
|
||||
append(& result, txt("·"));
|
||||
string_append_strc(& result, txt("·"));
|
||||
break;
|
||||
case '\t':
|
||||
append(& result, txt("→"));
|
||||
string_append_strc(& result, txt("→"));
|
||||
break;
|
||||
case '\n':
|
||||
append(& result, txt("↵"));
|
||||
string_append_strc(& result, txt("↵"));
|
||||
break;
|
||||
case '\r':
|
||||
append(& result, txt("⏎"));
|
||||
string_append_strc(& result, txt("⏎"));
|
||||
break;
|
||||
case '\v':
|
||||
append(& result, txt("⇕"));
|
||||
string_append_strc(& result, txt("⇕"));
|
||||
break;
|
||||
case '\f':
|
||||
append(& result, txt("⌂"));
|
||||
string_append_strc(& result, txt("⌂"));
|
||||
break;
|
||||
default:
|
||||
append(& result, c);
|
||||
string_append_char(& result, * c);
|
||||
break;
|
||||
}
|
||||
return to_strc(result);
|
||||
}
|
||||
return string_to_strc(result);
|
||||
}
|
||||
|
||||
// Represents strings cached with the string table.
|
||||
// Should never be modified, if changed string is desired, cache_string( str ) another.
|
||||
typedef StrC StringCached;
|
||||
|
||||
GEN_API_C_END
|
||||
|
||||
// Implements basic string interning. Data structure is based off the ZPL Hashtable.
|
||||
typedef HashTable<StringCached> StringTable;
|
||||
#pragma endregion Strings
|
||||
|
Reference in New Issue
Block a user