From 9d12c532d1b0f10fdf0a5c1fd05b43da98b8f82d Mon Sep 17 00:00:00 2001 From: Doyle T Date: Sun, 15 Jul 2018 02:17:34 +1000 Subject: [PATCH] Add lazy init to array/hash, rename 64bit max num, minor bug fixes --- DqnUnitTest.cpp | 10 +++--- dqn.h | 90 +++++++++++++++++++++++++++---------------------- 2 files changed, 54 insertions(+), 46 deletions(-) diff --git a/DqnUnitTest.cpp b/DqnUnitTest.cpp index 2c5f253..7386f93 100644 --- a/DqnUnitTest.cpp +++ b/DqnUnitTest.cpp @@ -206,27 +206,27 @@ void Dqn_Test() // i64 to str if (1) { - char a[DQN_64BIT_NUM_MAX_STR_SIZE] = {}; + char a[DQN_I64_MAX_STR_SIZE] = {}; Dqn_I64ToStr(+100, a, DQN_ARRAY_COUNT(a)); DQN_ASSERT(DqnStr_Cmp(a, "100") == 0); - char b[DQN_64BIT_NUM_MAX_STR_SIZE] = {}; + char b[DQN_I64_MAX_STR_SIZE] = {}; Dqn_I64ToStr(-100, b, DQN_ARRAY_COUNT(b)); DQN_ASSERT(DqnStr_Cmp(b, "-100") == 0); - char c[DQN_64BIT_NUM_MAX_STR_SIZE] = {}; + char c[DQN_I64_MAX_STR_SIZE] = {}; Dqn_I64ToStr(0, c, DQN_ARRAY_COUNT(c)); DQN_ASSERT(DqnStr_Cmp(c, "0") == 0); #if 0 - char d[DQN_64BIT_NUM_MAX_STR_SIZE] = {}; + char d[DQN_I64_MAX_STR_SIZE] = {}; Dqn_I64ToStr(LARGEST_NUM, d, DQN_ARRAY_COUNT(d)); DQN_ASSERT(DqnStr_Cmp(d, "18446744073709551615") == 0); #endif if (sizeof(size_t) == sizeof(u64)) { - char e[DQN_64BIT_NUM_MAX_STR_SIZE] = {}; + char e[DQN_I64_MAX_STR_SIZE] = {}; Dqn_I64ToStr(SMALLEST_NUM, e, DQN_ARRAY_COUNT(e)); DQN_ASSERTM(DqnStr_Cmp(e, "-9223372036854775808") == 0, "e: %s", e); } diff --git a/dqn.h b/dqn.h index f7d2442..98746fc 100644 --- a/dqn.h +++ b/dqn.h @@ -122,9 +122,9 @@ using b32 = i32; using f64 = double; using f32 = float; -#define DQN_F32_MIN -FLT_MAX; -#define DQN_I64_MAX INT64_MAX; -#define DQN_U64_MAX UINT64_MAX; +#define DQN_F32_MIN -FLT_MAX +#define DQN_I64_MAX INT64_MAX +#define DQN_U64_MAX UINT64_MAX #define DQN_TERABYTE(val) (DQN_GIGABYTE(val) * 1024LL) @@ -150,6 +150,7 @@ using f32 = float; #define DQN_DEGREES_TO_RADIANS(x) ((x * (DQN_PI / 180.0f))) #define DQN_RADIANS_TO_DEGREES(x) ((x * (180.0f / DQN_PI))) +#define DQN_CLAMP(value, min, max) DQN_MIN(DQN_MAX(value, min), max) #define DQN_MAX(a, b) ((a) < (b) ? (b) : (a)) #define DQN_MIN(a, b) ((a) < (b) ? (a) : (b)) #define DQN_SWAP(type, a, b) do { type tmp = a; a = b; b = tmp; } while(0) @@ -832,8 +833,8 @@ DQN_FILE_SCOPE inline DqnSlice DqnStr_RemoveLeadTrailQuotes (char const *s DQN_FILE_SCOPE inline DqnSlice DqnStr_RemoveLeadTrailBraces (char const *str, i32 strLen); -#define DQN_32BIT_NUM_MAX_STR_SIZE 11 -#define DQN_64BIT_NUM_MAX_STR_SIZE 21 +#define DQN_I32_MAX_STR_SIZE 11 +#define DQN_I64_MAX_STR_SIZE 21 // Return the len of the derived string. If buf is nullptr and or bufSize is 0 the function returns the // required string length for the integer // TODO NOTE(doyle): Parsing stops when a non-digit is encountered, so numbers with ',' don't work atm. @@ -1324,7 +1325,7 @@ struct DqnArray ~DqnArray () { if (this->data && this->memAPI) this->memAPI->Free(data); } void UseMemory (T *data_, isize max_, isize count_ = 0) { this->memAPI = nullptr; this->data = data_; this->max = max_; this->count = count_; } - void Clear (Dqn::ZeroClear clear = Dqn::ZeroClear::Yes) { if (data) { count = 0; if (clear == Dqn::ZeroClear::Yes) DqnMem_Clear(data, 0, sizeof(T) * max); } } + void Clear (Dqn::ZeroClear clear = Dqn::ZeroClear::No) { if (data) { count = 0; if (clear == Dqn::ZeroClear::Yes) DqnMem_Clear(data, 0, sizeof(T) * max); } } void Free () { if (data) { memAPI->Free(data); } *this = {}; } T *Front () { DQN_ASSERT(count > 0); return data + 0; } T *Back () { DQN_ASSERT(count > 0); return data + (count - 1); } @@ -2333,25 +2334,6 @@ int DqnFixedString::SprintfAppend(char const *fmt, ...) return result; } -template using DqnVHashTableHashingProc = isize(*)(isize count, Key const &data); -template using DqnVHashTableEqualsProc = bool (*)(Key const &a, Key const &b); - -#define DQN_VHASH_TABLE_HASHING_PROC(name) template inline isize name(isize count, Key const &key) -DQN_VHASH_TABLE_HASHING_PROC(DqnVHashTableDefaultHash) -{ - const u64 SEED = 0x9747B28CAB3F8A7B; - u64 index64 = DqnHash_Murmur64Seed(&key, sizeof(key), SEED); - isize result = index64 % count; - return result; -} - -#define DQN_VHASH_TABLE_EQUALS_PROC(name) template inline bool name(Key const &a, Key const &b) -DQN_VHASH_TABLE_EQUALS_PROC(DqnVHashTableDefaultEquals) -{ - bool result = (DqnMem_Cmp(&a, &b, sizeof(a)) == 0); - return result; -} - // TODO(doyle): Load factor // #DqnHashTable API // ================================================================================================= @@ -2914,22 +2896,25 @@ struct DqnVArray isize max; // Read T *data; // Read - DqnVArray () { count = 0; max = DQN_MEGABYTE(1) / sizeof(T); data = (T *)DqnOS_VAlloc(max * sizeof(T)); DQN_ASSERT(data); } - ~DqnVArray () { if (data) DqnOS_VFree(data, sizeof(T) * max); } - void Clear (Dqn::ZeroClear clear = Dqn::ZeroClear::Yes) { if (data) { count = 0; if (clear == Dqn::ZeroClear::Yes) DqnMem_Clear(data, 0, sizeof(T) * max); } } + DqnVArray () = default; + DqnVArray (isize size) { LazyInit(size); } + void LazyInit (isize size) { if (data) return; count = 0; max = size; data = (T *)DqnOS_VAlloc(max * sizeof(T)); DQN_ALWAYS_ASSERT(data); } + ~DqnVArray () { if (data) DqnOS_VFree(data, sizeof(T) * max); } + + void Clear (Dqn::ZeroClear clear = Dqn::ZeroClear::No) { if (data) { count = 0; if (clear == Dqn::ZeroClear::Yes) DqnMem_Clear(data, 0, sizeof(T) * max); } } void Free () { if (data) { DqnOS_VFree(data, sizeof(T) * max); } *this = {}; } - T *Front () { DQN_ASSERT(count > 0); return data + 0; } - T *Back () { DQN_ASSERT(count > 0); return data + (count - 1); } - T *Make (isize num = 1) { count += num; DQN_ASSERT(count < max); return &data[count - num]; } + T *Front () { return (count > 0) (data + 0) : nullptr; } + T *Back () { return (count > 0) (data + (count - 1)) : nullptr; } + T *Make (isize num = 1) { LazyInit(1024); count += num; DQN_ASSERT(count < max); return &data[count - num]; } T *Push (T const &v) { return Insert(count, &v, 1); } T *Push (T const *v, isize numItems = 1) { return Insert(count, v, numItems); } void Pop () { if (count > 0) count--; } - void Erase (isize index) { DQN_ASSERT(index >= 0 && index < count); data[index] = data[--count]; } + void Erase (isize index) { if (!data) return; DQN_ASSERT(index >= 0 && index < count); data[index] = data[--count]; } void EraseStable(isize index); T *Insert (isize index, T const *v) { return Insert(index, v, 1); } T *Insert (isize index, T const &v) { return Insert(index, &v, 1); } T *Insert (isize index, T const *v, isize numItems); - bool Contains (T const *v) const { T const *ptr = data; T const *end = data + count; while (ptr < end) if (*ptr++ == *v) return true; return false; } + bool Contains (T const *v) const { T const *ptr = data; T const *end = data + count; while (ptr < end) { if (*ptr++ == *v) return true; } return false; } T &operator[] (isize i) const { DQN_ASSERT(i < count && i > 0); return this->data[i]; } T *begin () { return data; } @@ -2938,7 +2923,9 @@ struct DqnVArray template T *DqnVArray::Insert(isize index, T const *v, isize numItems) { - index = DQN_MIN(DQN_MAX(index, 0), count); + LazyInit(1024); + + index = DQN_CLAMP(index, 0, count); isize const newCount = count + numItems; DQN_ASSERT(newCount < max); @@ -2957,6 +2944,7 @@ template T *DqnVArray::Insert(isize index, T const *v, isize numI template void DqnVArray::EraseStable(isize index) { + if (!data) return; DQN_ASSERT(index >= 0 && index < count); isize const off = (data + index) - data; memmove(data + off, data + off + 1, ((usize)count - (usize)off - 1) * sizeof(T)); @@ -2965,6 +2953,25 @@ template void DqnVArray::EraseStable(isize index) // #XPlatform > #DqnVHashTable API // ================================================================================================= +template using DqnVHashTableHashingProc = isize(*)(isize count, Key const &data); +template using DqnVHashTableEqualsProc = bool (*)(Key const &a, Key const &b); + +#define DQN_VHASH_TABLE_HASHING_PROC(name) template inline isize name(isize count, Key const &key) +DQN_VHASH_TABLE_HASHING_PROC(DqnVHashTableDefaultHash) +{ + const u64 SEED = 0x9747B28CAB3F8A7B; + u64 index64 = DqnHash_Murmur64Seed(&key, sizeof(key), SEED); + isize result = index64 % count; + return result; +} + +#define DQN_VHASH_TABLE_EQUALS_PROC(name) template inline bool name(Key const &a, Key const &b) +DQN_VHASH_TABLE_EQUALS_PROC(DqnVHashTableDefaultEquals) +{ + bool result = (DqnMem_Cmp(&a, &b, sizeof(a)) == 0); + return result; +} + #define DQN_VHASH_TABLE_TEMPLATE \ template (DqnOS_VAlloc(numBuckets * sizeof(*buckets))); DQN_ASSERT(buckets); } + void Erase (Key const &key); + Item *Set (Key const &key, Item const &item); + Item *Get (Key const &key); Item *operator[](Key const &key) { return Get(key); } -private: - void LazyInitialise(isize size) { *this = {}; numBuckets = size; buckets = static_cast(DqnOS_VAlloc(numBuckets * sizeof(*buckets))); DQN_ASSERT(buckets); } }; DQN_VHASH_TABLE_TEMPLATE Item *DQN_VHASH_TABLE_DECL::Set(Key const &key, Item const &item) { - if (!buckets) LazyInitialise(1024); + if (!buckets) LazyInit(1024); isize index = Hash(this->numBuckets, key); Bucket *bucket = this->buckets + index; @@ -6972,6 +6978,8 @@ DQN_FILE_SCOPE i64 Dqn_BSearch(i64 *array, i64 size, i64 find, DQN_FILE_SCOPE DqnJson DqnJson_Get(char const *buf, i32 bufLen, char const *findProperty, i32 findPropertyLen) { DqnJson result = {}; + if (!buf || bufLen == 0 || !findProperty || findPropertyLen == 0) return result; + char const *tmp = DqnChar_SkipWhitespace(buf); bufLen = static_cast((buf + bufLen) - tmp); buf = tmp;