Return true on resize to 0 for arrays
This commit is contained in:
		
							parent
							
								
									f838cc79bf
								
							
						
					
					
						commit
						87b7d3362c
					
				
							
								
								
									
										854
									
								
								dqn.h
									
									
									
									
									
								
							
							
						
						
									
										854
									
								
								dqn.h
									
									
									
									
									
								
							| @ -33,10 +33,8 @@ | |||||||
| // #DqnMem       Memory Allocation
 | // #DqnMem       Memory Allocation
 | ||||||
| // #DqnMemAPI    Custom memory API for Dqn Data Structures
 | // #DqnMemAPI    Custom memory API for Dqn Data Structures
 | ||||||
| // #DqnMemStack  Memory Allocator, Push, Pop Style
 | // #DqnMemStack  Memory Allocator, Push, Pop Style
 | ||||||
| // #DqnString    String library
 |  | ||||||
| // #DqnArray     Dynamic Array using Templates
 | // #DqnArray     Dynamic Array using Templates
 | ||||||
| // #DqnHash      Hashing using Murmur
 | // #DqnHash      Hashing using Murmur
 | ||||||
| // #DqnHashTable Hash Tables using Templates
 |  | ||||||
| // #DqnMath      Simple Math Helpers (Lerp etc.)
 | // #DqnMath      Simple Math Helpers (Lerp etc.)
 | ||||||
| // #DqnV2        2D  Math Vectors
 | // #DqnV2        2D  Math Vectors
 | ||||||
| // #DqnV3        3D  Math Vectors
 | // #DqnV3        3D  Math Vectors
 | ||||||
| @ -46,6 +44,8 @@ | |||||||
| // #DqnChar      Char  Operations (IsDigit(), IsAlpha() etc)
 | // #DqnChar      Char  Operations (IsDigit(), IsAlpha() etc)
 | ||||||
| // #DqnStr       Str   Operations (Str_Len(), Str_Copy() etc)
 | // #DqnStr       Str   Operations (Str_Len(), Str_Copy() etc)
 | ||||||
| // #DqnWChar     WChar Operations (IsDigit(), IsAlpha() etc)
 | // #DqnWChar     WChar Operations (IsDigit(), IsAlpha() etc)
 | ||||||
|  | // #DqnString    String library
 | ||||||
|  | // #DqnHashTable Hash Tables using Templates
 | ||||||
| // #DqnRnd       Random Number Generator (ints and floats)
 | // #DqnRnd       Random Number Generator (ints and floats)
 | ||||||
| // #Dqn_*        Utility code, (qsort, quick file reading)
 | // #Dqn_*        Utility code, (qsort, quick file reading)
 | ||||||
| 
 | 
 | ||||||
| @ -175,7 +175,7 @@ using f32 = float; | |||||||
| 	{                                                                                              \ | 	{                                                                                              \ | ||||||
| 		if (!(expr))                                                                               \ | 		if (!(expr))                                                                               \ | ||||||
| 		{                                                                                          \ | 		{                                                                                          \ | ||||||
| 			DqnLog(__FILE__, __func__, __LINE__, #expr, msg, ##__VA_ARGS__);                       \ | 			DqnLogExpr(__FILE__, __func__, __LINE__, #expr, msg, ##__VA_ARGS__);                       \ | ||||||
| 			(*((int *)0)) = 0;                                                                     \ | 			(*((int *)0)) = 0;                                                                     \ | ||||||
| 		}                                                                                          \ | 		}                                                                                          \ | ||||||
| 	} while (0) | 	} while (0) | ||||||
| @ -185,7 +185,7 @@ using f32 = float; | |||||||
| 
 | 
 | ||||||
| // Use macro above.
 | // Use macro above.
 | ||||||
| DQN_FILE_SCOPE void DqnLog(char *file, char const *const functionName, i32 const lineNum, char const *const msg, ...); | DQN_FILE_SCOPE void DqnLog(char *file, char const *const functionName, i32 const lineNum, char const *const msg, ...); | ||||||
| DQN_FILE_SCOPE void DqnLog(char *file, char const *const functionName, i32 const lineNum, char const *const expr, char const *const msg, ...); | DQN_FILE_SCOPE void DqnLogExpr(char *file, char const *const functionName, i32 const lineNum, char const *const expr, char const *const msg, ...); | ||||||
| 
 | 
 | ||||||
| // Assert at compile time by making a type that is invalid depending on the expression result
 | // Assert at compile time by making a type that is invalid depending on the expression result
 | ||||||
| #define DQN_COMPILE_ASSERT(expr)                DQN_COMPILE_ASSERT_INTERNAL(expr, DQN_UNIQUE_NAME(DqnCompileAssertInternal_)) | #define DQN_COMPILE_ASSERT(expr)                DQN_COMPILE_ASSERT_INTERNAL(expr, DQN_UNIQUE_NAME(DqnCompileAssertInternal_)) | ||||||
| @ -434,83 +434,6 @@ struct DqnMemStack | |||||||
|     void   FreeDetachedBlock      (Block *memBlock); |     void   FreeDetachedBlock      (Block *memBlock); | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| // #DqnString Public API - String library
 |  | ||||||
| // =================================================================================================
 |  | ||||||
| // String allocates +1 extra byte for the null-terminator to be completely compatible with
 |  | ||||||
| // C style strings, but this is not reflected in the capacity or len, and is hidden from the user.
 |  | ||||||
| 
 |  | ||||||
| // Usage: DqnString example = DQN_STRING_LITERAL(example, "hello world");
 |  | ||||||
| #define DQN_STRING_LITERAL(srcVariable, literal)                                                   \ |  | ||||||
| 	DQN_STRING_LITERAL_INTERNAL(srcVariable, literal, DQN_UNIQUE_NAME(dqnstring_)) |  | ||||||
| 
 |  | ||||||
| class DqnString |  | ||||||
| { |  | ||||||
| 
 |  | ||||||
| public: |  | ||||||
| 	DqnMemAPI *memAPI; |  | ||||||
| 	i32        len;              // Len of the string in bytes not including null-terminator
 |  | ||||||
| 	i32        max;              // The maximum capacity not including space for null-terminator.
 |  | ||||||
| 	char      *str; |  | ||||||
| 
 |  | ||||||
| 	// Initialisation API
 |  | ||||||
| 	// =============================================================================================
 |  | ||||||
| 	void Init              (DqnMemAPI   *const api = &DQN_DEFAULT_HEAP_ALLOCATOR); |  | ||||||
| 	void Init              (DqnMemStack *const stack); |  | ||||||
| 
 |  | ||||||
| 	// return: False if (size < 0) or (memAPI allocation failed).
 |  | ||||||
| 	bool InitSize          (i32 size, DqnMemStack *const stack); |  | ||||||
| 	bool InitSize          (i32 size, DqnMemAPI   *const api = &DQN_DEFAULT_HEAP_ALLOCATOR); |  | ||||||
| 
 |  | ||||||
| 	// return: False if arguments are invalid.
 |  | ||||||
| 	bool InitFixedMem      (char *const memory, const i32 sizeInBytes); |  | ||||||
| 
 |  | ||||||
| 	bool InitLiteral       (char    const *const cstr, i32 const lenInBytes, DqnMemStack *const stack); |  | ||||||
| 	bool InitLiteral       (char    const *const cstr,                       DqnMemStack *const stack); |  | ||||||
| 	bool InitLiteral       (char    const *const cstr, i32 const lenInBytes, DqnMemAPI   *const api = &DQN_DEFAULT_HEAP_ALLOCATOR); |  | ||||||
| 	bool InitLiteral       (char    const *const cstr,                       DqnMemAPI   *const api = &DQN_DEFAULT_HEAP_ALLOCATOR); |  | ||||||
| 
 |  | ||||||
| 	bool InitLiteral       (wchar_t const *const cstr, DqnMemStack *const stack); |  | ||||||
| 	bool InitLiteral       (wchar_t const *const cstr, DqnMemAPI   *const api = &DQN_DEFAULT_HEAP_ALLOCATOR); |  | ||||||
| 
 |  | ||||||
| 	// return: False if cstr is nullptr.
 |  | ||||||
| 	bool InitLiteralNoAlloc(char *const cstr, i32 cstrLen = -1); |  | ||||||
| 
 |  | ||||||
| 	// API
 |  | ||||||
| 	// =============================================================================================
 |  | ||||||
| 	// return: These functions return false if allocation failed. String is preserved.
 |  | ||||||
| 	bool     Expand  (i32 newMax); |  | ||||||
| 	bool     Sprintf (char      const *const fmt, ...); |  | ||||||
| 	bool     VSprintf(char      const *const fmt, va_list argList); |  | ||||||
| 	bool     Append  (DqnString const        string); |  | ||||||
| 	bool     Append  (DqnString const       *string); |  | ||||||
| 	bool     Append  (char      const *const cstr, i32 bytesToCopy = -1); |  | ||||||
| 
 |  | ||||||
| 	void     Clear   (); |  | ||||||
| 	void     Free    (); |  | ||||||
| 
 |  | ||||||
| 	// return: -1 if invalid, or if bufSize is 0 the required buffer length in wchar_t characters
 |  | ||||||
| 	i32      ToWChar(wchar_t *const buf, i32 const bufSize) const; |  | ||||||
| 
 |  | ||||||
| 	// return: String allocated using api.
 |  | ||||||
| 	wchar_t *ToWChar(DqnMemAPI *const api = &DQN_DEFAULT_HEAP_ALLOCATOR) const; |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| class DqnSmartString : public DqnString |  | ||||||
| { |  | ||||||
| public: |  | ||||||
| 	~DqnSmartString() { this->Free(); } |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| DQN_FILE_SCOPE DqnString DqnString_(DqnMemAPI   *const api = &DQN_DEFAULT_HEAP_ALLOCATOR); |  | ||||||
| DQN_FILE_SCOPE DqnString DqnString_(DqnMemStack *const stack); |  | ||||||
| 
 |  | ||||||
| // NOTE: First level of indirection needs to turn the combined dqnstring_(guid) into a name. Otherwise
 |  | ||||||
| //       each use of literalVarName will increment __COUNTER__
 |  | ||||||
| #define DQN_STRING_LITERAL_INTERNAL(srcVariable, literal, literalVarName)                          \ |  | ||||||
| 	{};                                                                                            \ |  | ||||||
| 	char literalVarName[] = literal;                                                               \ |  | ||||||
| 	srcVariable.InitLiteralNoAlloc(literalVarName, DQN_CHAR_COUNT(literalVarName)) |  | ||||||
| 
 |  | ||||||
| // #DqnArray API
 | // #DqnArray API
 | ||||||
| // =================================================================================================
 | // =================================================================================================
 | ||||||
| #define DQN_FOR_ARRAY(indexName, arrayPtr)                                                         \ | #define DQN_FOR_ARRAY(indexName, arrayPtr)                                                         \ | ||||||
| @ -644,7 +567,7 @@ bool DqnArray<T>::Resize(isize newMax) | |||||||
| 		DQN_LOGD( | 		DQN_LOGD( | ||||||
| 		    "DqnArray tried to resize to 0 items. Not allowed? TODO(doyle): Maybe just free the " | 		    "DqnArray tried to resize to 0 items. Not allowed? TODO(doyle): Maybe just free the " | ||||||
| 		    "array then?"); | 		    "array then?"); | ||||||
| 		return false; | 		return true; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| @ -922,6 +845,417 @@ DQN_FILE_SCOPE inline u64 DqnHash_Murmur64(void const *data, size_t len) | |||||||
| 	return DqnHash_Murmur64Seed(data, len, 0x9747b28c); | 	return DqnHash_Murmur64Seed(data, len, 0x9747b28c); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | // #DqnMath API
 | ||||||
|  | // =================================================================================================
 | ||||||
|  | DQN_FILE_SCOPE f32 DqnMath_Lerp  (f32 a, f32 t, f32 b); | ||||||
|  | DQN_FILE_SCOPE f32 DqnMath_Sqrtf (f32 a); | ||||||
|  | DQN_FILE_SCOPE f32 DqnMath_Clampf(f32 val, f32 min, f32 max); | ||||||
|  | 
 | ||||||
|  | // #DqnV2 API
 | ||||||
|  | // =================================================================================================
 | ||||||
|  | union DqnV2i | ||||||
|  | { | ||||||
|  | 	struct { i32 x, y; }; | ||||||
|  | 	struct { i32 w, h; }; | ||||||
|  | 	struct { i32 min, max; }; | ||||||
|  | 	i32 e[2]; | ||||||
|  | 
 | ||||||
|  | 	bool operator==(DqnV2i const &b) const { return (this->x == b.x) && (this->y == b.y); } | ||||||
|  | 	bool operator!=(DqnV2i const &b) const { return !(*this == b); } | ||||||
|  | 	bool operator>=(DqnV2i const &b) const { return (this->x >= b.x) && (this->y >= b.y); } | ||||||
|  | 	bool operator<=(DqnV2i const &b) const { return (this->x <= b.x) && (this->y <= b.y); } | ||||||
|  | 	bool operator< (DqnV2i const &b) const { return (this->x <  b.x) && (this->y <  b.y); } | ||||||
|  | 	bool operator> (DqnV2i const &b) const { return (this->x >  b.x) && (this->y >  b.y); } | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | union DqnV2 | ||||||
|  | { | ||||||
|  | 	struct { f32 x, y; }; | ||||||
|  | 	struct { f32 w, h; }; | ||||||
|  | 	struct { f32 min, max; }; | ||||||
|  | 	f32 e[2]; | ||||||
|  | 
 | ||||||
|  | 	bool operator==(DqnV2 const &b) const { return (this->x == b.x) && (this->y == b.y); } | ||||||
|  | 	bool operator!=(DqnV2 const &b) const { return !(*this == b); } | ||||||
|  | 	bool operator>=(DqnV2 const &b) const { return (this->x >= b.x) && (this->y >= b.y); } | ||||||
|  | 	bool operator<=(DqnV2 const &b) const { return (this->x <= b.x) && (this->y <= b.y); } | ||||||
|  | 	bool operator< (DqnV2 const &b) const { return (this->x <  b.x) && (this->y <  b.y); } | ||||||
|  | 	bool operator> (DqnV2 const &b) const { return (this->x >  b.x) && (this->y >  b.y); } | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | DQN_FILE_SCOPE DqnV2 DqnV2_(f32 xy); | ||||||
|  | DQN_FILE_SCOPE DqnV2 DqnV2_(f32 x, f32 y); | ||||||
|  | DQN_FILE_SCOPE DqnV2 DqnV2_(i32 x, i32 y); | ||||||
|  | DQN_FILE_SCOPE DqnV2 DqnV2_(DqnV2i a); | ||||||
|  | 
 | ||||||
|  | DQN_FILE_SCOPE DqnV2 DqnV2_Add     (DqnV2 a, DqnV2 b); | ||||||
|  | DQN_FILE_SCOPE DqnV2 DqnV2_Sub     (DqnV2 a, DqnV2 b); | ||||||
|  | DQN_FILE_SCOPE DqnV2 DqnV2_Scalei  (DqnV2 a, i32 b); | ||||||
|  | DQN_FILE_SCOPE DqnV2 DqnV2_Scalef  (DqnV2 a, f32 b); | ||||||
|  | DQN_FILE_SCOPE DqnV2 DqnV2_Hadamard(DqnV2 a, DqnV2 b); | ||||||
|  | DQN_FILE_SCOPE f32   DqnV2_Dot     (DqnV2 a, DqnV2 b); | ||||||
|  | DQN_FILE_SCOPE bool  DqnV2_Equals  (DqnV2 a, DqnV2 b); | ||||||
|  | 
 | ||||||
|  | DQN_FILE_SCOPE f32   DqnV2_LengthSquared(const DqnV2 a, const DqnV2 b); | ||||||
|  | DQN_FILE_SCOPE f32   DqnV2_Length       (const DqnV2 a, const DqnV2 b); | ||||||
|  | DQN_FILE_SCOPE DqnV2 DqnV2_Normalise    (const DqnV2 a); | ||||||
|  | DQN_FILE_SCOPE bool  DqnV2_Overlaps     (      DqnV2 a,       DqnV2 b); | ||||||
|  | DQN_FILE_SCOPE DqnV2 DqnV2_Perpendicular(const DqnV2 a); | ||||||
|  | 
 | ||||||
|  | DQN_FILE_SCOPE DqnV2 DqnV2_ResizeKeepAspectRatio(DqnV2 srcSize, DqnV2 targetSize); | ||||||
|  | DQN_FILE_SCOPE DqnV2 DqnV2_ConstrainToRatio     (DqnV2 dim, DqnV2 ratio); // Resize the dimension to fit the aspect ratio provided. Downscale only.
 | ||||||
|  | 
 | ||||||
|  | DQN_FILE_SCOPE inline DqnV2  operator- (DqnV2  a, DqnV2 b) { return      DqnV2_Sub     (a, b);  } | ||||||
|  | DQN_FILE_SCOPE inline DqnV2  operator+ (DqnV2  a, DqnV2 b) { return      DqnV2_Add     (a, b);  } | ||||||
|  | DQN_FILE_SCOPE inline DqnV2  operator* (DqnV2  a, DqnV2 b) { return      DqnV2_Hadamard(a, b);  } | ||||||
|  | DQN_FILE_SCOPE inline DqnV2  operator* (DqnV2  a, f32   b) { return      DqnV2_Scalef  (a, b);  } | ||||||
|  | DQN_FILE_SCOPE inline DqnV2  operator* (DqnV2  a, i32   b) { return      DqnV2_Scalei  (a, b);  } | ||||||
|  | DQN_FILE_SCOPE inline DqnV2 &operator*=(DqnV2 &a, DqnV2 b) { return (a = DqnV2_Hadamard(a, b)); } | ||||||
|  | DQN_FILE_SCOPE inline DqnV2 &operator*=(DqnV2 &a, f32   b) { return (a = DqnV2_Scalef  (a, b)); } | ||||||
|  | DQN_FILE_SCOPE inline DqnV2 &operator*=(DqnV2 &a, i32   b) { return (a = DqnV2_Scalei  (a, b)); } | ||||||
|  | DQN_FILE_SCOPE inline DqnV2 &operator-=(DqnV2 &a, DqnV2 b) { return (a = DqnV2_Sub     (a, b)); } | ||||||
|  | DQN_FILE_SCOPE inline DqnV2 &operator+=(DqnV2 &a, DqnV2 b) { return (a = DqnV2_Add     (a, b)); } | ||||||
|  | 
 | ||||||
|  | // DqnV2i
 | ||||||
|  | DQN_FILE_SCOPE DqnV2i DqnV2i_(i32 x_, i32 y_); | ||||||
|  | DQN_FILE_SCOPE DqnV2i DqnV2i_(f32 x_, f32 y_); | ||||||
|  | DQN_FILE_SCOPE DqnV2i DqnV2i_(DqnV2 a); | ||||||
|  | 
 | ||||||
|  | DQN_FILE_SCOPE DqnV2i DqnV2i_Add     (DqnV2i a, DqnV2i b); | ||||||
|  | DQN_FILE_SCOPE DqnV2i DqnV2i_Sub     (DqnV2i a, DqnV2i b); | ||||||
|  | DQN_FILE_SCOPE DqnV2i DqnV2i_Scalei  (DqnV2i a, i32 b); | ||||||
|  | DQN_FILE_SCOPE DqnV2i DqnV2i_Scalef  (DqnV2i a, f32 b); | ||||||
|  | DQN_FILE_SCOPE DqnV2i DqnV2i_Hadamard(DqnV2i a, DqnV2i b); | ||||||
|  | DQN_FILE_SCOPE f32    DqnV2i_Dot     (DqnV2i a, DqnV2i b); | ||||||
|  | DQN_FILE_SCOPE bool   DqnV2i_Equals  (DqnV2i a, DqnV2i b); | ||||||
|  | 
 | ||||||
|  | DQN_FILE_SCOPE inline DqnV2i  operator- (DqnV2i  a, DqnV2i b) { return      DqnV2i_Sub     (a, b);  } | ||||||
|  | DQN_FILE_SCOPE inline DqnV2i  operator+ (DqnV2i  a, DqnV2i b) { return      DqnV2i_Add     (a, b);  } | ||||||
|  | DQN_FILE_SCOPE inline DqnV2i  operator* (DqnV2i  a, DqnV2i b) { return      DqnV2i_Hadamard(a, b);  } | ||||||
|  | DQN_FILE_SCOPE inline DqnV2i  operator* (DqnV2i  a, f32    b) { return      DqnV2i_Scalef  (a, b);  } | ||||||
|  | DQN_FILE_SCOPE inline DqnV2i  operator* (DqnV2i  a, i32    b) { return      DqnV2i_Scalei  (a, b);  } | ||||||
|  | DQN_FILE_SCOPE inline DqnV2i &operator*=(DqnV2i &a, DqnV2i b) { return (a = DqnV2i_Hadamard(a, b)); } | ||||||
|  | DQN_FILE_SCOPE inline DqnV2i &operator-=(DqnV2i &a, DqnV2i b) { return (a = DqnV2i_Sub     (a, b)); } | ||||||
|  | DQN_FILE_SCOPE inline DqnV2i &operator+=(DqnV2i &a, DqnV2i b) { return (a = DqnV2i_Add     (a, b)); } | ||||||
|  | 
 | ||||||
|  | // #DqnV3 API
 | ||||||
|  | // =================================================================================================
 | ||||||
|  | union DqnV3 | ||||||
|  | { | ||||||
|  | 		struct { f32 x, y, z; }; | ||||||
|  | 		DqnV2 xy; | ||||||
|  | 		struct { f32 r, g, b; }; | ||||||
|  | 		f32 e[3]; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | union DqnV3i | ||||||
|  | { | ||||||
|  | 	struct { i32 x, y, z; }; | ||||||
|  | 	struct { i32 r, g, b; }; | ||||||
|  | 	i32 e[3]; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | // DqnV3
 | ||||||
|  | DQN_FILE_SCOPE DqnV3 DqnV3_(f32 xyz); | ||||||
|  | DQN_FILE_SCOPE DqnV3 DqnV3_(f32 x, f32 y, f32 z); | ||||||
|  | DQN_FILE_SCOPE DqnV3 DqnV3_(i32 x, i32 y, i32 z); | ||||||
|  | 
 | ||||||
|  | DQN_FILE_SCOPE DqnV3 DqnV3_Add     (DqnV3 a, DqnV3 b); | ||||||
|  | DQN_FILE_SCOPE DqnV3 DqnV3_Sub     (DqnV3 a, DqnV3 b); | ||||||
|  | DQN_FILE_SCOPE DqnV3 DqnV3_Scalei  (DqnV3 a, i32 b); | ||||||
|  | DQN_FILE_SCOPE DqnV3 DqnV3_Scalef  (DqnV3 a, f32 b); | ||||||
|  | DQN_FILE_SCOPE DqnV3 DqnV3_Hadamard(DqnV3 a, DqnV3 b); | ||||||
|  | DQN_FILE_SCOPE f32   DqnV3_Dot     (DqnV3 a, DqnV3 b); | ||||||
|  | DQN_FILE_SCOPE bool  DqnV3_Equals  (DqnV3 a, DqnV3 b); | ||||||
|  | DQN_FILE_SCOPE DqnV3 DqnV3_Cross   (DqnV3 a, DqnV3 b); | ||||||
|  | 
 | ||||||
|  | DQN_FILE_SCOPE DqnV3 DqnV3_Normalise    (DqnV3 a); | ||||||
|  | DQN_FILE_SCOPE f32   DqnV3_Length       (DqnV3 a, DqnV3 b); | ||||||
|  | DQN_FILE_SCOPE f32   DqnV3_LengthSquared(DqnV3 a, DqnV3 b); | ||||||
|  | 
 | ||||||
|  | DQN_FILE_SCOPE inline DqnV3  operator- (DqnV3  a, DqnV3 b) { return      DqnV3_Sub     (a, b);           } | ||||||
|  | DQN_FILE_SCOPE inline DqnV3  operator+ (DqnV3  a, DqnV3 b) { return      DqnV3_Add     (a, b);           } | ||||||
|  | DQN_FILE_SCOPE inline DqnV3  operator+ (DqnV3  a, f32   b) { return      DqnV3_Add     (a, DqnV3_(b));   } | ||||||
|  | DQN_FILE_SCOPE inline DqnV3  operator* (DqnV3  a, DqnV3 b) { return      DqnV3_Hadamard(a, b);           } | ||||||
|  | DQN_FILE_SCOPE inline DqnV3  operator* (DqnV3  a, f32   b) { return      DqnV3_Scalef  (a, b);           } | ||||||
|  | DQN_FILE_SCOPE inline DqnV3  operator* (DqnV3  a, i32   b) { return      DqnV3_Scalei  (a, b);           } | ||||||
|  | DQN_FILE_SCOPE inline DqnV3  operator/ (DqnV3  a, f32   b) { return      DqnV3_Scalef  (a, (1.0f/b));    } | ||||||
|  | DQN_FILE_SCOPE inline DqnV3 &operator*=(DqnV3 &a, DqnV3 b) { return (a = DqnV3_Hadamard(a, b));          } | ||||||
|  | DQN_FILE_SCOPE inline DqnV3 &operator*=(DqnV3 &a, f32   b) { return (a = DqnV3_Scalef  (a, b));          } | ||||||
|  | DQN_FILE_SCOPE inline DqnV3 &operator*=(DqnV3 &a, i32   b) { return (a = DqnV3_Scalei  (a, b));          } | ||||||
|  | DQN_FILE_SCOPE inline DqnV3 &operator-=(DqnV3 &a, DqnV3 b) { return (a = DqnV3_Sub     (a, b));          } | ||||||
|  | DQN_FILE_SCOPE inline DqnV3 &operator+=(DqnV3 &a, DqnV3 b) { return (a = DqnV3_Add     (a, b));          } | ||||||
|  | DQN_FILE_SCOPE inline bool   operator==(DqnV3  a, DqnV3 b) { return      DqnV3_Equals  (a, b);           } | ||||||
|  | 
 | ||||||
|  | DQN_FILE_SCOPE DqnV3i DqnV3i_(i32 x, i32 y, i32 z); | ||||||
|  | DQN_FILE_SCOPE DqnV3i DqnV3i_(f32 x, f32 y, f32 z); | ||||||
|  | 
 | ||||||
|  | // #DqnV4 API
 | ||||||
|  | // =================================================================================================
 | ||||||
|  | union DqnV4 | ||||||
|  | { | ||||||
|  | 	struct { f32 x, y, z, w; }; | ||||||
|  | 	DqnV3 xyz; | ||||||
|  | 	DqnV2 xy; | ||||||
|  | 
 | ||||||
|  | 	struct { f32 r, g, b, a; }; | ||||||
|  | 	DqnV3 rgb; | ||||||
|  | 
 | ||||||
|  | 	f32    e[4]; | ||||||
|  | 	DqnV2 v2[2]; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | DQN_FILE_SCOPE DqnV4 DqnV4_(); | ||||||
|  | DQN_FILE_SCOPE DqnV4 DqnV4_(f32 xyzw); | ||||||
|  | DQN_FILE_SCOPE DqnV4 DqnV4_(f32 x, f32 y, f32 z, f32 w); | ||||||
|  | DQN_FILE_SCOPE DqnV4 DqnV4_(i32 x, i32 y, i32 z, i32 w); | ||||||
|  | DQN_FILE_SCOPE DqnV4 DqnV4_(DqnV3 a, f32 w); | ||||||
|  | 
 | ||||||
|  | DQN_FILE_SCOPE DqnV4 DqnV4_Add     (DqnV4 a, DqnV4 b); | ||||||
|  | DQN_FILE_SCOPE DqnV4 DqnV4_Sub     (DqnV4 a, DqnV4 b); | ||||||
|  | DQN_FILE_SCOPE DqnV4 DqnV4_Scalef  (DqnV4 a, f32 b); | ||||||
|  | DQN_FILE_SCOPE DqnV4 DqnV4_Scalei  (DqnV4 a, i32 b); | ||||||
|  | DQN_FILE_SCOPE DqnV4 DqnV4_Hadamard(DqnV4 a, DqnV4 b); | ||||||
|  | DQN_FILE_SCOPE f32   DqnV4_Dot     (DqnV4 a, DqnV4 b); | ||||||
|  | DQN_FILE_SCOPE bool  DqnV4_Equals  (DqnV4 a, DqnV4 b); | ||||||
|  | 
 | ||||||
|  | DQN_FILE_SCOPE inline DqnV4  operator- (DqnV4  a, DqnV4 b) { return      DqnV4_Sub     (a, b);            } | ||||||
|  | DQN_FILE_SCOPE inline DqnV4  operator+ (DqnV4  a, DqnV4 b) { return      DqnV4_Add     (a, b);            } | ||||||
|  | DQN_FILE_SCOPE inline DqnV4  operator+ (DqnV4  a, f32   b) { return      DqnV4_Add     (a, DqnV4_(b));    } | ||||||
|  | DQN_FILE_SCOPE inline DqnV4  operator* (DqnV4  a, DqnV4 b) { return      DqnV4_Hadamard(a, b);            } | ||||||
|  | DQN_FILE_SCOPE inline DqnV4  operator* (DqnV4  a, f32   b) { return      DqnV4_Scalef  (a, b);            } | ||||||
|  | DQN_FILE_SCOPE inline DqnV4  operator* (DqnV4  a, i32   b) { return      DqnV4_Scalei  (a, b);            } | ||||||
|  | DQN_FILE_SCOPE inline DqnV4 &operator*=(DqnV4 &a, DqnV4 b) { return (a = DqnV4_Hadamard(a, b));           } | ||||||
|  | DQN_FILE_SCOPE inline DqnV4 &operator*=(DqnV4 &a, f32   b) { return (a = DqnV4_Scalef  (a, b));           } | ||||||
|  | DQN_FILE_SCOPE inline DqnV4 &operator*=(DqnV4 &a, i32   b) { return (a = DqnV4_Scalei  (a, b));           } | ||||||
|  | DQN_FILE_SCOPE inline DqnV4 &operator-=(DqnV4 &a, DqnV4 b) { return (a = DqnV4_Sub     (a, b));           } | ||||||
|  | DQN_FILE_SCOPE inline DqnV4 &operator+=(DqnV4 &a, DqnV4 b) { return (a = DqnV4_Add     (a, b));           } | ||||||
|  | DQN_FILE_SCOPE inline bool   operator==(DqnV4 &a, DqnV4 b) { return      DqnV4_Equals  (a, b);            } | ||||||
|  | 
 | ||||||
|  | // #DqnMat4 API
 | ||||||
|  | // =================================================================================================
 | ||||||
|  | typedef union DqnMat4 | ||||||
|  | { | ||||||
|  | 	// TODO(doyle): Row/column instead? More cache friendly since multiplication
 | ||||||
|  | 	// prefers rows.
 | ||||||
|  | 	DqnV4 col[4]; | ||||||
|  | 	f32   e[4][4]; // Column/row
 | ||||||
|  | } DqnMat4; | ||||||
|  | 
 | ||||||
|  | DQN_FILE_SCOPE DqnMat4 DqnMat4_Identity    (); | ||||||
|  | 
 | ||||||
|  | DQN_FILE_SCOPE DqnMat4 DqnMat4_Orthographic(f32 left, f32 right, f32 bottom, f32 top, f32 zNear, f32 zFar); | ||||||
|  | DQN_FILE_SCOPE DqnMat4 DqnMat4_Perspective (f32 fovYDegrees, f32 aspectRatio, f32 zNear, f32 zFar); | ||||||
|  | DQN_FILE_SCOPE DqnMat4 DqnMat4_LookAt      (DqnV3 eye, DqnV3 center, DqnV3 up); | ||||||
|  | 
 | ||||||
|  | DQN_FILE_SCOPE DqnMat4 DqnMat4_Translate3f (f32 x, f32 y, f32 z); | ||||||
|  | DQN_FILE_SCOPE DqnMat4 DqnMat4_TranslateV3 (DqnV3 vec); | ||||||
|  | DQN_FILE_SCOPE DqnMat4 DqnMat4_Rotate      (f32 radians, f32 x, f32 y, f32 z); | ||||||
|  | DQN_FILE_SCOPE DqnMat4 DqnMat4_Scale       (f32 x, f32 y, f32 z); | ||||||
|  | DQN_FILE_SCOPE DqnMat4 DqnMat4_ScaleV3     (DqnV3 scale); | ||||||
|  | DQN_FILE_SCOPE DqnMat4 DqnMat4_Mul         (DqnMat4 a, DqnMat4 b); | ||||||
|  | DQN_FILE_SCOPE DqnV4   DqnMat4_MulV4       (DqnMat4 a, DqnV4 b); | ||||||
|  | 
 | ||||||
|  | // #DqnRect API
 | ||||||
|  | // =================================================================================================
 | ||||||
|  | class DqnRect | ||||||
|  | { | ||||||
|  | public: | ||||||
|  | 	DqnV2 min; | ||||||
|  | 	DqnV2 max; | ||||||
|  | 
 | ||||||
|  | 	f32   GetWidth ()                                    const { return max.w - min.w; } | ||||||
|  | 	f32   GetHeight()                                    const { return max.h - min.h; } | ||||||
|  | 	DqnV2 GetSize  ()                                    const { return max - min;     } | ||||||
|  | 	void  GetSize  (f32 *const width, f32 *const height) const; | ||||||
|  | 	DqnV2 GetCenter()                                    const; | ||||||
|  | 
 | ||||||
|  | 	DqnRect ClipRect (DqnRect const clip) const; | ||||||
|  | 	DqnRect Move     (DqnV2   const shift)  const; | ||||||
|  | 	bool    ContainsP(DqnV2   const p)      const; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | DQN_FILE_SCOPE DqnRect DqnRect_(DqnV2 origin, DqnV2 size); | ||||||
|  | DQN_FILE_SCOPE DqnRect DqnRect_(f32 x, f32 y, f32 w, f32 h); | ||||||
|  | DQN_FILE_SCOPE DqnRect DqnRect_(i32 x, i32 y, i32 w, i32 h); | ||||||
|  | 
 | ||||||
|  | // #DqnChar API
 | ||||||
|  | // =================================================================================================
 | ||||||
|  | DQN_FILE_SCOPE char DqnChar_ToLower     (char c); | ||||||
|  | DQN_FILE_SCOPE char DqnChar_ToUpper     (char c); | ||||||
|  | DQN_FILE_SCOPE bool DqnChar_IsDigit     (char c); | ||||||
|  | DQN_FILE_SCOPE bool DqnChar_IsAlpha     (char c); | ||||||
|  | DQN_FILE_SCOPE bool DqnChar_IsAlphaNum  (char c); | ||||||
|  | DQN_FILE_SCOPE bool DqnChar_IsEndOfLine (char c); | ||||||
|  | DQN_FILE_SCOPE bool DqnChar_IsWhitespace(char c); | ||||||
|  | 
 | ||||||
|  | DQN_FILE_SCOPE char *DqnChar_TrimWhitespaceAround(char const *src, i32 srcLen, i32 *newLen); | ||||||
|  | DQN_FILE_SCOPE char *DqnChar_SkipWhitespace      (char const *ptr); | ||||||
|  | 
 | ||||||
|  | // TODO(doyle): this is NOT UTF8 safe
 | ||||||
|  | // ch:        Char to find
 | ||||||
|  | // len:       The length of the string stored in ptr, (doesn't care if it includes null terminator)
 | ||||||
|  | // lenToChar: The length to the char from end of the ptr, i.e. (ptr + len)
 | ||||||
|  | // return:    The ptr to the last char, null if it could not find.
 | ||||||
|  | DQN_FILE_SCOPE char *DqnChar_FindLastChar  (char *ptr, char const ch, i32 len, u32 *const lenToChar); | ||||||
|  | 
 | ||||||
|  | // Finds up to the first [\r]\n and destroy the line, giving you a null terminated line at the newline.
 | ||||||
|  | // returns: The value to advance the ptr by, this can be different from the line
 | ||||||
|  | //          length if there are new lines or leading whitespaces in the next line
 | ||||||
|  | DQN_FILE_SCOPE i32   DqnChar_FindNextLine(char *ptr, i32 *lineLength); | ||||||
|  | DQN_FILE_SCOPE char *DqnChar_GetNextLine (char *ptr, i32 *lineLength); | ||||||
|  | 
 | ||||||
|  | // #DqnStr API
 | ||||||
|  | // =================================================================================================
 | ||||||
|  | // numBytesToCompare: If -1, cmp runs until \0 is encountered.
 | ||||||
|  | // return:            0 if equal. 0 < if a is before b, > 0 if a is after b
 | ||||||
|  | DQN_FILE_SCOPE i32   DqnStr_Cmp               (char const *const a, char const *const b, i32 numBytesToCompare = -1, bool ignoreCase = false); | ||||||
|  | 
 | ||||||
|  | // strLen: Len of string, if -1, StrLen is used.
 | ||||||
|  | // return: Pointer in str to the last slash, if none then the original string.
 | ||||||
|  | DQN_FILE_SCOPE char *DqnStr_GetPtrToLastSlash (char const *str, i32 strLen = -1); | ||||||
|  | 
 | ||||||
|  | // return: String length not including the nullptr terminator. 0 if invalid args.
 | ||||||
|  | DQN_FILE_SCOPE i32   DqnStr_Len               (char const *const a); | ||||||
|  | DQN_FILE_SCOPE i32   DqnStr_LenUTF8           (u32 const *const a, i32 *const lenInBytes = nullptr); | ||||||
|  | 
 | ||||||
|  | // return: String length starting from a, up to and not including the first delimiter character.
 | ||||||
|  | DQN_FILE_SCOPE i32   DqnStr_LenDelimitWith    (char *const a, char const delimiter); | ||||||
|  | 
 | ||||||
|  | // return: The dest argument, nullptr if args invalid (i.e. nullptr pointers or numChars < 0)
 | ||||||
|  | DQN_FILE_SCOPE char *DqnStr_Copy              (char *const dest, char const *const src, i32 const numChars); | ||||||
|  | DQN_FILE_SCOPE void  DqnStr_Reverse           (char *const buf, i32 const bufSize); | ||||||
|  | 
 | ||||||
|  | // return: Number of bytes in codepoint, 0 if *a becomes invalid or end of stream.
 | ||||||
|  | DQN_FILE_SCOPE i32   DqnStr_ReadUTF8Codepoint (u32 const *const a, u32 *outCodepoint); | ||||||
|  | 
 | ||||||
|  | // return: The offset into the src to first char of the found string. Returns -1 if not found
 | ||||||
|  | DQN_FILE_SCOPE i32   DqnStr_FindFirstOccurence(char const *src, i32 srcLen, char const *find, i32 findLen, bool ignoreCase = false); | ||||||
|  | DQN_FILE_SCOPE bool  DqnStr_EndsWith          (char const *src, i32 srcLen, char const *find, i32 findLen, bool ignoreCase = false); | ||||||
|  | 
 | ||||||
|  | // return: Helper function that returns the pointer to the first occurence, nullptr if not found.
 | ||||||
|  | DQN_FILE_SCOPE char *DqnStr_GetFirstOccurence (char const *src, i32 srcLen, char const *find, i32 findLen, bool ignoreCase = false); | ||||||
|  | DQN_FILE_SCOPE bool  DqnStr_HasSubstring      (char const *src, i32 srcLen, char const *find, i32 findLen, bool ignoreCase = false); | ||||||
|  | 
 | ||||||
|  | #define DQN_32BIT_NUM_MAX_STR_SIZE 11 | ||||||
|  | #define DQN_64BIT_NUM_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.
 | ||||||
|  | DQN_FILE_SCOPE i32 Dqn_I64ToStr(i64 const value, char *const buf, i32 const bufSize); | ||||||
|  | DQN_FILE_SCOPE i64 Dqn_StrToI64(char const *const buf, i64 const bufSize); | ||||||
|  | // WARNING: Not robust, precision errors and whatnot but good enough!
 | ||||||
|  | DQN_FILE_SCOPE f32 Dqn_StrToF32(char const *const buf, i64 const bufSize); | ||||||
|  | 
 | ||||||
|  | // Both return the number of bytes read, return 0 if invalid codepoint or UTF8
 | ||||||
|  | DQN_FILE_SCOPE u32 Dqn_UCSToUTF8(u32 *const dest, u32 const character); | ||||||
|  | DQN_FILE_SCOPE u32 Dqn_UTF8ToUCS(u32 *const dest, u32 const character); | ||||||
|  | 
 | ||||||
|  | // #DqnWChar API
 | ||||||
|  | // =================================================================================================
 | ||||||
|  | // NOTE: See above for documentation
 | ||||||
|  | DQN_FILE_SCOPE bool     DqnWChar_IsDigit          (wchar_t const c); | ||||||
|  | DQN_FILE_SCOPE wchar_t  DqnWChar_ToLower          (wchar_t const c); | ||||||
|  | 
 | ||||||
|  | DQN_FILE_SCOPE wchar_t *DqnWChar_SkipWhitespace   (wchar_t *ptr); | ||||||
|  | DQN_FILE_SCOPE wchar_t *DqnWChar_FindLastChar     (wchar_t *ptr, const wchar_t ch, i32 len, u32 *const lenToChar); | ||||||
|  | DQN_FILE_SCOPE i32      DqnWChar_GetNextLine      (const wchar_t *ptr, i32 *lineLength); | ||||||
|  | 
 | ||||||
|  | DQN_FILE_SCOPE i32      DqnWStr_Cmp               (wchar_t const *const a, const wchar_t *const b); | ||||||
|  | DQN_FILE_SCOPE i32      DqnWStr_FindFirstOccurence(wchar_t const *const src, i32 const srcLen, wchar_t const *const find, i32 const findLen); | ||||||
|  | DQN_FILE_SCOPE bool     DqnWStr_HasSubstring      (wchar_t const *const src, i32 const srcLen, wchar_t const *const find, i32 const findLen); | ||||||
|  | DQN_FILE_SCOPE i32      DqnWStr_Len               (wchar_t const *const a); | ||||||
|  | DQN_FILE_SCOPE i32      DqnWStr_LenDelimitWith    (wchar_t const *const a, wchar_t const delimiter); | ||||||
|  | DQN_FILE_SCOPE void     DqnWStr_Reverse           (wchar_t *const buf, u32 const bufSize); | ||||||
|  | 
 | ||||||
|  | DQN_FILE_SCOPE i32      Dqn_WStrToI32             (wchar_t const *const buf, i32 const bufSize); | ||||||
|  | DQN_FILE_SCOPE i32      Dqn_I32ToWStr             (i32 value, wchar_t *buf, i32 bufSize); | ||||||
|  | 
 | ||||||
|  | // #DqnString Public API - String library
 | ||||||
|  | // =================================================================================================
 | ||||||
|  | // String allocates +1 extra byte for the null-terminator to be completely compatible with
 | ||||||
|  | // C style strings, but this is not reflected in the capacity or len, and is hidden from the user.
 | ||||||
|  | 
 | ||||||
|  | // Usage: DqnString example = DQN_STRING_LITERAL(example, "hello world");
 | ||||||
|  | #define DQN_STRING_LITERAL(srcVariable, literal)                                                   \ | ||||||
|  | 	DQN_STRING_LITERAL_INTERNAL(srcVariable, literal, DQN_UNIQUE_NAME(dqnstring_)) | ||||||
|  | 
 | ||||||
|  | class DqnString | ||||||
|  | { | ||||||
|  | 
 | ||||||
|  | public: | ||||||
|  | 	DqnMemAPI *memAPI; | ||||||
|  | 	i32        len;              // Len of the string in bytes not including null-terminator
 | ||||||
|  | 	i32        max;              // The maximum capacity not including space for null-terminator.
 | ||||||
|  | 	char      *str; | ||||||
|  | 
 | ||||||
|  | 	// Initialisation API
 | ||||||
|  | 	// =============================================================================================
 | ||||||
|  | 	void Init              (DqnMemAPI   *const api = &DQN_DEFAULT_HEAP_ALLOCATOR); | ||||||
|  | 	void Init              (DqnMemStack *const stack); | ||||||
|  | 
 | ||||||
|  | 	// return: False if (size < 0) or (memAPI allocation failed).
 | ||||||
|  | 	bool InitSize          (i32 size, DqnMemStack *const stack); | ||||||
|  | 	bool InitSize          (i32 size, DqnMemAPI   *const api = &DQN_DEFAULT_HEAP_ALLOCATOR); | ||||||
|  | 
 | ||||||
|  | 	// return: False if arguments are invalid.
 | ||||||
|  | 	bool InitFixedMem      (char *const memory, const i32 sizeInBytes); | ||||||
|  | 
 | ||||||
|  | 	bool InitLiteral       (char    const *const cstr, i32 const lenInBytes, DqnMemStack *const stack); | ||||||
|  | 	bool InitLiteral       (char    const *const cstr,                       DqnMemStack *const stack); | ||||||
|  | 	bool InitLiteral       (char    const *const cstr, i32 const lenInBytes, DqnMemAPI   *const api = &DQN_DEFAULT_HEAP_ALLOCATOR); | ||||||
|  | 	bool InitLiteral       (char    const *const cstr,                       DqnMemAPI   *const api = &DQN_DEFAULT_HEAP_ALLOCATOR); | ||||||
|  | 
 | ||||||
|  | 	bool InitLiteral       (wchar_t const *const cstr, DqnMemStack *const stack); | ||||||
|  | 	bool InitLiteral       (wchar_t const *const cstr, DqnMemAPI   *const api = &DQN_DEFAULT_HEAP_ALLOCATOR); | ||||||
|  | 
 | ||||||
|  | 	// return: False if cstr is nullptr.
 | ||||||
|  | 	bool InitLiteralNoAlloc(char *const cstr, i32 cstrLen = -1); | ||||||
|  | 
 | ||||||
|  | 	// API
 | ||||||
|  | 	// =============================================================================================
 | ||||||
|  | 	// return: These functions return false if allocation failed. String is preserved.
 | ||||||
|  | 	bool     Expand  (i32 newMax); | ||||||
|  | 	bool     Sprintf (char      const *const fmt, ...); | ||||||
|  | 	bool     VSprintf(char      const *const fmt, va_list argList); | ||||||
|  | 	bool     Append  (DqnString const        string); | ||||||
|  | 	bool     Append  (DqnString const       *string); | ||||||
|  | 	bool     Append  (char      const *const cstr, i32 bytesToCopy = -1); | ||||||
|  | 
 | ||||||
|  | 	void     Clear   (); | ||||||
|  | 	void     Free    (); | ||||||
|  | 
 | ||||||
|  | 	// return: -1 if invalid, or if bufSize is 0 the required buffer length in wchar_t characters
 | ||||||
|  | 	i32      ToWChar(wchar_t *const buf, i32 const bufSize) const; | ||||||
|  | 
 | ||||||
|  | 	// return: String allocated using api.
 | ||||||
|  | 	wchar_t *ToWChar(DqnMemAPI *const api = &DQN_DEFAULT_HEAP_ALLOCATOR) const; | ||||||
|  | 
 | ||||||
|  | 	// Statics
 | ||||||
|  | 	// =============================================================================================
 | ||||||
|  | 	static bool Cmp(DqnString const *a, DqnString const *b, bool ignoreCase = false) | ||||||
|  | 	{ | ||||||
|  | 		bool result = (a->len == b->len) && (DqnStr_Cmp(a->str, b->str, a->len, ignoreCase) == 0); | ||||||
|  | 		return result; | ||||||
|  | 	} | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | class DqnSmartString : public DqnString | ||||||
|  | { | ||||||
|  | public: | ||||||
|  | 	~DqnSmartString() { this->Free(); } | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | DQN_FILE_SCOPE DqnString DqnString_(DqnMemAPI   *const api = &DQN_DEFAULT_HEAP_ALLOCATOR); | ||||||
|  | DQN_FILE_SCOPE DqnString DqnString_(DqnMemStack *const stack); | ||||||
|  | 
 | ||||||
|  | // NOTE: First level of indirection needs to turn the combined dqnstring_(guid) into a name. Otherwise
 | ||||||
|  | //       each use of literalVarName will increment __COUNTER__
 | ||||||
|  | #define DQN_STRING_LITERAL_INTERNAL(srcVariable, literal, literalVarName)                          \ | ||||||
|  | 	{};                                                                                            \ | ||||||
|  | 	char literalVarName[] = literal;                                                               \ | ||||||
|  | 	srcVariable.InitLiteralNoAlloc(literalVarName, DQN_CHAR_COUNT(literalVarName)) | ||||||
|  | 
 | ||||||
| // #DqnHashTable API
 | // #DqnHashTable API
 | ||||||
| // =================================================================================================
 | // =================================================================================================
 | ||||||
| template <typename T> | template <typename T> | ||||||
| @ -1406,331 +1740,6 @@ bool DqnHashTable<T>::ChangeNumEntries(i64 newNumEntries) | |||||||
| 	return true; | 	return true; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // #DqnMath API
 |  | ||||||
| // =================================================================================================
 |  | ||||||
| DQN_FILE_SCOPE f32 DqnMath_Lerp  (f32 a, f32 t, f32 b); |  | ||||||
| DQN_FILE_SCOPE f32 DqnMath_Sqrtf (f32 a); |  | ||||||
| DQN_FILE_SCOPE f32 DqnMath_Clampf(f32 val, f32 min, f32 max); |  | ||||||
| 
 |  | ||||||
| // #DqnV2 API
 |  | ||||||
| // =================================================================================================
 |  | ||||||
| union DqnV2i |  | ||||||
| { |  | ||||||
| 	struct { i32 x, y; }; |  | ||||||
| 	struct { i32 w, h; }; |  | ||||||
| 	struct { i32 min, max; }; |  | ||||||
| 	i32 e[2]; |  | ||||||
| 
 |  | ||||||
| 	bool operator==(DqnV2i const &b) const { return (this->x == b.x) && (this->y == b.y); } |  | ||||||
| 	bool operator!=(DqnV2i const &b) const { return !(*this == b); } |  | ||||||
| 	bool operator>=(DqnV2i const &b) const { return (this->x >= b.x) && (this->y >= b.y); } |  | ||||||
| 	bool operator<=(DqnV2i const &b) const { return (this->x <= b.x) && (this->y <= b.y); } |  | ||||||
| 	bool operator< (DqnV2i const &b) const { return (this->x <  b.x) && (this->y <  b.y); } |  | ||||||
| 	bool operator> (DqnV2i const &b) const { return (this->x >  b.x) && (this->y >  b.y); } |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| union DqnV2 |  | ||||||
| { |  | ||||||
| 	struct { f32 x, y; }; |  | ||||||
| 	struct { f32 w, h; }; |  | ||||||
| 	struct { f32 min, max; }; |  | ||||||
| 	f32 e[2]; |  | ||||||
| 
 |  | ||||||
| 	bool operator==(DqnV2 const &b) const { return (this->x == b.x) && (this->y == b.y); } |  | ||||||
| 	bool operator!=(DqnV2 const &b) const { return !(*this == b); } |  | ||||||
| 	bool operator>=(DqnV2 const &b) const { return (this->x >= b.x) && (this->y >= b.y); } |  | ||||||
| 	bool operator<=(DqnV2 const &b) const { return (this->x <= b.x) && (this->y <= b.y); } |  | ||||||
| 	bool operator< (DqnV2 const &b) const { return (this->x <  b.x) && (this->y <  b.y); } |  | ||||||
| 	bool operator> (DqnV2 const &b) const { return (this->x >  b.x) && (this->y >  b.y); } |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| DQN_FILE_SCOPE DqnV2 DqnV2_(f32 xy); |  | ||||||
| DQN_FILE_SCOPE DqnV2 DqnV2_(f32 x, f32 y); |  | ||||||
| DQN_FILE_SCOPE DqnV2 DqnV2_(i32 x, i32 y); |  | ||||||
| DQN_FILE_SCOPE DqnV2 DqnV2_(DqnV2i a); |  | ||||||
| 
 |  | ||||||
| DQN_FILE_SCOPE DqnV2 DqnV2_Add     (DqnV2 a, DqnV2 b); |  | ||||||
| DQN_FILE_SCOPE DqnV2 DqnV2_Sub     (DqnV2 a, DqnV2 b); |  | ||||||
| DQN_FILE_SCOPE DqnV2 DqnV2_Scalei  (DqnV2 a, i32 b); |  | ||||||
| DQN_FILE_SCOPE DqnV2 DqnV2_Scalef  (DqnV2 a, f32 b); |  | ||||||
| DQN_FILE_SCOPE DqnV2 DqnV2_Hadamard(DqnV2 a, DqnV2 b); |  | ||||||
| DQN_FILE_SCOPE f32   DqnV2_Dot     (DqnV2 a, DqnV2 b); |  | ||||||
| DQN_FILE_SCOPE bool  DqnV2_Equals  (DqnV2 a, DqnV2 b); |  | ||||||
| 
 |  | ||||||
| DQN_FILE_SCOPE f32   DqnV2_LengthSquared(const DqnV2 a, const DqnV2 b); |  | ||||||
| DQN_FILE_SCOPE f32   DqnV2_Length       (const DqnV2 a, const DqnV2 b); |  | ||||||
| DQN_FILE_SCOPE DqnV2 DqnV2_Normalise    (const DqnV2 a); |  | ||||||
| DQN_FILE_SCOPE bool  DqnV2_Overlaps     (      DqnV2 a,       DqnV2 b); |  | ||||||
| DQN_FILE_SCOPE DqnV2 DqnV2_Perpendicular(const DqnV2 a); |  | ||||||
| 
 |  | ||||||
| DQN_FILE_SCOPE DqnV2 DqnV2_ResizeKeepAspectRatio(DqnV2 srcSize, DqnV2 targetSize); |  | ||||||
| DQN_FILE_SCOPE DqnV2 DqnV2_ConstrainToRatio     (DqnV2 dim, DqnV2 ratio); // Resize the dimension to fit the aspect ratio provided. Downscale only.
 |  | ||||||
| 
 |  | ||||||
| DQN_FILE_SCOPE inline DqnV2  operator- (DqnV2  a, DqnV2 b) { return      DqnV2_Sub     (a, b);  } |  | ||||||
| DQN_FILE_SCOPE inline DqnV2  operator+ (DqnV2  a, DqnV2 b) { return      DqnV2_Add     (a, b);  } |  | ||||||
| DQN_FILE_SCOPE inline DqnV2  operator* (DqnV2  a, DqnV2 b) { return      DqnV2_Hadamard(a, b);  } |  | ||||||
| DQN_FILE_SCOPE inline DqnV2  operator* (DqnV2  a, f32   b) { return      DqnV2_Scalef  (a, b);  } |  | ||||||
| DQN_FILE_SCOPE inline DqnV2  operator* (DqnV2  a, i32   b) { return      DqnV2_Scalei  (a, b);  } |  | ||||||
| DQN_FILE_SCOPE inline DqnV2 &operator*=(DqnV2 &a, DqnV2 b) { return (a = DqnV2_Hadamard(a, b)); } |  | ||||||
| DQN_FILE_SCOPE inline DqnV2 &operator*=(DqnV2 &a, f32   b) { return (a = DqnV2_Scalef  (a, b)); } |  | ||||||
| DQN_FILE_SCOPE inline DqnV2 &operator*=(DqnV2 &a, i32   b) { return (a = DqnV2_Scalei  (a, b)); } |  | ||||||
| DQN_FILE_SCOPE inline DqnV2 &operator-=(DqnV2 &a, DqnV2 b) { return (a = DqnV2_Sub     (a, b)); } |  | ||||||
| DQN_FILE_SCOPE inline DqnV2 &operator+=(DqnV2 &a, DqnV2 b) { return (a = DqnV2_Add     (a, b)); } |  | ||||||
| 
 |  | ||||||
| // DqnV2i
 |  | ||||||
| DQN_FILE_SCOPE DqnV2i DqnV2i_(i32 x_, i32 y_); |  | ||||||
| DQN_FILE_SCOPE DqnV2i DqnV2i_(f32 x_, f32 y_); |  | ||||||
| DQN_FILE_SCOPE DqnV2i DqnV2i_(DqnV2 a); |  | ||||||
| 
 |  | ||||||
| DQN_FILE_SCOPE DqnV2i DqnV2i_Add     (DqnV2i a, DqnV2i b); |  | ||||||
| DQN_FILE_SCOPE DqnV2i DqnV2i_Sub     (DqnV2i a, DqnV2i b); |  | ||||||
| DQN_FILE_SCOPE DqnV2i DqnV2i_Scalei  (DqnV2i a, i32 b); |  | ||||||
| DQN_FILE_SCOPE DqnV2i DqnV2i_Scalef  (DqnV2i a, f32 b); |  | ||||||
| DQN_FILE_SCOPE DqnV2i DqnV2i_Hadamard(DqnV2i a, DqnV2i b); |  | ||||||
| DQN_FILE_SCOPE f32    DqnV2i_Dot     (DqnV2i a, DqnV2i b); |  | ||||||
| DQN_FILE_SCOPE bool   DqnV2i_Equals  (DqnV2i a, DqnV2i b); |  | ||||||
| 
 |  | ||||||
| DQN_FILE_SCOPE inline DqnV2i  operator- (DqnV2i  a, DqnV2i b) { return      DqnV2i_Sub     (a, b);  } |  | ||||||
| DQN_FILE_SCOPE inline DqnV2i  operator+ (DqnV2i  a, DqnV2i b) { return      DqnV2i_Add     (a, b);  } |  | ||||||
| DQN_FILE_SCOPE inline DqnV2i  operator* (DqnV2i  a, DqnV2i b) { return      DqnV2i_Hadamard(a, b);  } |  | ||||||
| DQN_FILE_SCOPE inline DqnV2i  operator* (DqnV2i  a, f32    b) { return      DqnV2i_Scalef  (a, b);  } |  | ||||||
| DQN_FILE_SCOPE inline DqnV2i  operator* (DqnV2i  a, i32    b) { return      DqnV2i_Scalei  (a, b);  } |  | ||||||
| DQN_FILE_SCOPE inline DqnV2i &operator*=(DqnV2i &a, DqnV2i b) { return (a = DqnV2i_Hadamard(a, b)); } |  | ||||||
| DQN_FILE_SCOPE inline DqnV2i &operator-=(DqnV2i &a, DqnV2i b) { return (a = DqnV2i_Sub     (a, b)); } |  | ||||||
| DQN_FILE_SCOPE inline DqnV2i &operator+=(DqnV2i &a, DqnV2i b) { return (a = DqnV2i_Add     (a, b)); } |  | ||||||
| 
 |  | ||||||
| // #DqnV3 API
 |  | ||||||
| // =================================================================================================
 |  | ||||||
| union DqnV3 |  | ||||||
| { |  | ||||||
| 		struct { f32 x, y, z; }; |  | ||||||
| 		DqnV2 xy; |  | ||||||
| 		struct { f32 r, g, b; }; |  | ||||||
| 		f32 e[3]; |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| union DqnV3i |  | ||||||
| { |  | ||||||
| 	struct { i32 x, y, z; }; |  | ||||||
| 	struct { i32 r, g, b; }; |  | ||||||
| 	i32 e[3]; |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| // DqnV3
 |  | ||||||
| DQN_FILE_SCOPE DqnV3 DqnV3_(f32 xyz); |  | ||||||
| DQN_FILE_SCOPE DqnV3 DqnV3_(f32 x, f32 y, f32 z); |  | ||||||
| DQN_FILE_SCOPE DqnV3 DqnV3_(i32 x, i32 y, i32 z); |  | ||||||
| 
 |  | ||||||
| DQN_FILE_SCOPE DqnV3 DqnV3_Add     (DqnV3 a, DqnV3 b); |  | ||||||
| DQN_FILE_SCOPE DqnV3 DqnV3_Sub     (DqnV3 a, DqnV3 b); |  | ||||||
| DQN_FILE_SCOPE DqnV3 DqnV3_Scalei  (DqnV3 a, i32 b); |  | ||||||
| DQN_FILE_SCOPE DqnV3 DqnV3_Scalef  (DqnV3 a, f32 b); |  | ||||||
| DQN_FILE_SCOPE DqnV3 DqnV3_Hadamard(DqnV3 a, DqnV3 b); |  | ||||||
| DQN_FILE_SCOPE f32   DqnV3_Dot     (DqnV3 a, DqnV3 b); |  | ||||||
| DQN_FILE_SCOPE bool  DqnV3_Equals  (DqnV3 a, DqnV3 b); |  | ||||||
| DQN_FILE_SCOPE DqnV3 DqnV3_Cross   (DqnV3 a, DqnV3 b); |  | ||||||
| 
 |  | ||||||
| DQN_FILE_SCOPE DqnV3 DqnV3_Normalise    (DqnV3 a); |  | ||||||
| DQN_FILE_SCOPE f32   DqnV3_Length       (DqnV3 a, DqnV3 b); |  | ||||||
| DQN_FILE_SCOPE f32   DqnV3_LengthSquared(DqnV3 a, DqnV3 b); |  | ||||||
| 
 |  | ||||||
| DQN_FILE_SCOPE inline DqnV3  operator- (DqnV3  a, DqnV3 b) { return      DqnV3_Sub     (a, b);           } |  | ||||||
| DQN_FILE_SCOPE inline DqnV3  operator+ (DqnV3  a, DqnV3 b) { return      DqnV3_Add     (a, b);           } |  | ||||||
| DQN_FILE_SCOPE inline DqnV3  operator+ (DqnV3  a, f32   b) { return      DqnV3_Add     (a, DqnV3_(b));   } |  | ||||||
| DQN_FILE_SCOPE inline DqnV3  operator* (DqnV3  a, DqnV3 b) { return      DqnV3_Hadamard(a, b);           } |  | ||||||
| DQN_FILE_SCOPE inline DqnV3  operator* (DqnV3  a, f32   b) { return      DqnV3_Scalef  (a, b);           } |  | ||||||
| DQN_FILE_SCOPE inline DqnV3  operator* (DqnV3  a, i32   b) { return      DqnV3_Scalei  (a, b);           } |  | ||||||
| DQN_FILE_SCOPE inline DqnV3  operator/ (DqnV3  a, f32   b) { return      DqnV3_Scalef  (a, (1.0f/b));    } |  | ||||||
| DQN_FILE_SCOPE inline DqnV3 &operator*=(DqnV3 &a, DqnV3 b) { return (a = DqnV3_Hadamard(a, b));          } |  | ||||||
| DQN_FILE_SCOPE inline DqnV3 &operator*=(DqnV3 &a, f32   b) { return (a = DqnV3_Scalef  (a, b));          } |  | ||||||
| DQN_FILE_SCOPE inline DqnV3 &operator*=(DqnV3 &a, i32   b) { return (a = DqnV3_Scalei  (a, b));          } |  | ||||||
| DQN_FILE_SCOPE inline DqnV3 &operator-=(DqnV3 &a, DqnV3 b) { return (a = DqnV3_Sub     (a, b));          } |  | ||||||
| DQN_FILE_SCOPE inline DqnV3 &operator+=(DqnV3 &a, DqnV3 b) { return (a = DqnV3_Add     (a, b));          } |  | ||||||
| DQN_FILE_SCOPE inline bool   operator==(DqnV3  a, DqnV3 b) { return      DqnV3_Equals  (a, b);           } |  | ||||||
| 
 |  | ||||||
| DQN_FILE_SCOPE DqnV3i DqnV3i_(i32 x, i32 y, i32 z); |  | ||||||
| DQN_FILE_SCOPE DqnV3i DqnV3i_(f32 x, f32 y, f32 z); |  | ||||||
| 
 |  | ||||||
| // #DqnV4 API
 |  | ||||||
| // =================================================================================================
 |  | ||||||
| union DqnV4 |  | ||||||
| { |  | ||||||
| 	struct { f32 x, y, z, w; }; |  | ||||||
| 	DqnV3 xyz; |  | ||||||
| 	DqnV2 xy; |  | ||||||
| 
 |  | ||||||
| 	struct { f32 r, g, b, a; }; |  | ||||||
| 	DqnV3 rgb; |  | ||||||
| 
 |  | ||||||
| 	f32    e[4]; |  | ||||||
| 	DqnV2 v2[2]; |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| DQN_FILE_SCOPE DqnV4 DqnV4_(); |  | ||||||
| DQN_FILE_SCOPE DqnV4 DqnV4_(f32 xyzw); |  | ||||||
| DQN_FILE_SCOPE DqnV4 DqnV4_(f32 x, f32 y, f32 z, f32 w); |  | ||||||
| DQN_FILE_SCOPE DqnV4 DqnV4_(i32 x, i32 y, i32 z, i32 w); |  | ||||||
| DQN_FILE_SCOPE DqnV4 DqnV4_(DqnV3 a, f32 w); |  | ||||||
| 
 |  | ||||||
| DQN_FILE_SCOPE DqnV4 DqnV4_Add     (DqnV4 a, DqnV4 b); |  | ||||||
| DQN_FILE_SCOPE DqnV4 DqnV4_Sub     (DqnV4 a, DqnV4 b); |  | ||||||
| DQN_FILE_SCOPE DqnV4 DqnV4_Scalef  (DqnV4 a, f32 b); |  | ||||||
| DQN_FILE_SCOPE DqnV4 DqnV4_Scalei  (DqnV4 a, i32 b); |  | ||||||
| DQN_FILE_SCOPE DqnV4 DqnV4_Hadamard(DqnV4 a, DqnV4 b); |  | ||||||
| DQN_FILE_SCOPE f32   DqnV4_Dot     (DqnV4 a, DqnV4 b); |  | ||||||
| DQN_FILE_SCOPE bool  DqnV4_Equals  (DqnV4 a, DqnV4 b); |  | ||||||
| 
 |  | ||||||
| DQN_FILE_SCOPE inline DqnV4  operator- (DqnV4  a, DqnV4 b) { return      DqnV4_Sub     (a, b);            } |  | ||||||
| DQN_FILE_SCOPE inline DqnV4  operator+ (DqnV4  a, DqnV4 b) { return      DqnV4_Add     (a, b);            } |  | ||||||
| DQN_FILE_SCOPE inline DqnV4  operator+ (DqnV4  a, f32   b) { return      DqnV4_Add     (a, DqnV4_(b));    } |  | ||||||
| DQN_FILE_SCOPE inline DqnV4  operator* (DqnV4  a, DqnV4 b) { return      DqnV4_Hadamard(a, b);            } |  | ||||||
| DQN_FILE_SCOPE inline DqnV4  operator* (DqnV4  a, f32   b) { return      DqnV4_Scalef  (a, b);            } |  | ||||||
| DQN_FILE_SCOPE inline DqnV4  operator* (DqnV4  a, i32   b) { return      DqnV4_Scalei  (a, b);            } |  | ||||||
| DQN_FILE_SCOPE inline DqnV4 &operator*=(DqnV4 &a, DqnV4 b) { return (a = DqnV4_Hadamard(a, b));           } |  | ||||||
| DQN_FILE_SCOPE inline DqnV4 &operator*=(DqnV4 &a, f32   b) { return (a = DqnV4_Scalef  (a, b));           } |  | ||||||
| DQN_FILE_SCOPE inline DqnV4 &operator*=(DqnV4 &a, i32   b) { return (a = DqnV4_Scalei  (a, b));           } |  | ||||||
| DQN_FILE_SCOPE inline DqnV4 &operator-=(DqnV4 &a, DqnV4 b) { return (a = DqnV4_Sub     (a, b));           } |  | ||||||
| DQN_FILE_SCOPE inline DqnV4 &operator+=(DqnV4 &a, DqnV4 b) { return (a = DqnV4_Add     (a, b));           } |  | ||||||
| DQN_FILE_SCOPE inline bool   operator==(DqnV4 &a, DqnV4 b) { return      DqnV4_Equals  (a, b);            } |  | ||||||
| 
 |  | ||||||
| // #DqnMat4 API
 |  | ||||||
| // =================================================================================================
 |  | ||||||
| typedef union DqnMat4 |  | ||||||
| { |  | ||||||
| 	// TODO(doyle): Row/column instead? More cache friendly since multiplication
 |  | ||||||
| 	// prefers rows.
 |  | ||||||
| 	DqnV4 col[4]; |  | ||||||
| 	f32   e[4][4]; // Column/row
 |  | ||||||
| } DqnMat4; |  | ||||||
| 
 |  | ||||||
| DQN_FILE_SCOPE DqnMat4 DqnMat4_Identity    (); |  | ||||||
| 
 |  | ||||||
| DQN_FILE_SCOPE DqnMat4 DqnMat4_Orthographic(f32 left, f32 right, f32 bottom, f32 top, f32 zNear, f32 zFar); |  | ||||||
| DQN_FILE_SCOPE DqnMat4 DqnMat4_Perspective (f32 fovYDegrees, f32 aspectRatio, f32 zNear, f32 zFar); |  | ||||||
| DQN_FILE_SCOPE DqnMat4 DqnMat4_LookAt      (DqnV3 eye, DqnV3 center, DqnV3 up); |  | ||||||
| 
 |  | ||||||
| DQN_FILE_SCOPE DqnMat4 DqnMat4_Translate3f (f32 x, f32 y, f32 z); |  | ||||||
| DQN_FILE_SCOPE DqnMat4 DqnMat4_TranslateV3 (DqnV3 vec); |  | ||||||
| DQN_FILE_SCOPE DqnMat4 DqnMat4_Rotate      (f32 radians, f32 x, f32 y, f32 z); |  | ||||||
| DQN_FILE_SCOPE DqnMat4 DqnMat4_Scale       (f32 x, f32 y, f32 z); |  | ||||||
| DQN_FILE_SCOPE DqnMat4 DqnMat4_ScaleV3     (DqnV3 scale); |  | ||||||
| DQN_FILE_SCOPE DqnMat4 DqnMat4_Mul         (DqnMat4 a, DqnMat4 b); |  | ||||||
| DQN_FILE_SCOPE DqnV4   DqnMat4_MulV4       (DqnMat4 a, DqnV4 b); |  | ||||||
| 
 |  | ||||||
| // #DqnRect API
 |  | ||||||
| // =================================================================================================
 |  | ||||||
| class DqnRect |  | ||||||
| { |  | ||||||
| public: |  | ||||||
| 	DqnV2 min; |  | ||||||
| 	DqnV2 max; |  | ||||||
| 
 |  | ||||||
| 	f32   GetWidth ()                                    const { return max.w - min.w; } |  | ||||||
| 	f32   GetHeight()                                    const { return max.h - min.h; } |  | ||||||
| 	DqnV2 GetSize  ()                                    const { return max - min;     } |  | ||||||
| 	void  GetSize  (f32 *const width, f32 *const height) const; |  | ||||||
| 	DqnV2 GetCenter()                                    const; |  | ||||||
| 
 |  | ||||||
| 	DqnRect ClipRect (DqnRect const clip) const; |  | ||||||
| 	DqnRect Move     (DqnV2   const shift)  const; |  | ||||||
| 	bool    ContainsP(DqnV2   const p)      const; |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| DQN_FILE_SCOPE DqnRect DqnRect_(DqnV2 origin, DqnV2 size); |  | ||||||
| DQN_FILE_SCOPE DqnRect DqnRect_(f32 x, f32 y, f32 w, f32 h); |  | ||||||
| DQN_FILE_SCOPE DqnRect DqnRect_(i32 x, i32 y, i32 w, i32 h); |  | ||||||
| 
 |  | ||||||
| // #DqnChar API
 |  | ||||||
| // =================================================================================================
 |  | ||||||
| DQN_FILE_SCOPE char DqnChar_ToLower     (char c); |  | ||||||
| DQN_FILE_SCOPE char DqnChar_ToUpper     (char c); |  | ||||||
| DQN_FILE_SCOPE bool DqnChar_IsDigit     (char c); |  | ||||||
| DQN_FILE_SCOPE bool DqnChar_IsAlpha     (char c); |  | ||||||
| DQN_FILE_SCOPE bool DqnChar_IsAlphaNum  (char c); |  | ||||||
| DQN_FILE_SCOPE bool DqnChar_IsEndOfLine (char c); |  | ||||||
| DQN_FILE_SCOPE bool DqnChar_IsWhitespace(char c); |  | ||||||
| 
 |  | ||||||
| DQN_FILE_SCOPE char *DqnChar_TrimWhitespaceAround(char const *src, i32 srcLen, i32 *newLen); |  | ||||||
| DQN_FILE_SCOPE char *DqnChar_SkipWhitespace      (char const *ptr); |  | ||||||
| 
 |  | ||||||
| // TODO(doyle): this is NOT UTF8 safe
 |  | ||||||
| // ch:        Char to find
 |  | ||||||
| // len:       The length of the string stored in ptr, (doesn't care if it includes null terminator)
 |  | ||||||
| // lenToChar: The length to the char from end of the ptr, i.e. (ptr + len)
 |  | ||||||
| // return:    The ptr to the last char, null if it could not find.
 |  | ||||||
| DQN_FILE_SCOPE char *DqnChar_FindLastChar  (char *ptr, char const ch, i32 len, u32 *const lenToChar); |  | ||||||
| 
 |  | ||||||
| // Finds up to the first [\r]\n and destroy the line, giving you a null terminated line at the newline.
 |  | ||||||
| // returns: The value to advance the ptr by, this can be different from the line
 |  | ||||||
| //          length if there are new lines or leading whitespaces in the next line
 |  | ||||||
| DQN_FILE_SCOPE i32   DqnChar_FindNextLine(char *ptr, i32 *lineLength); |  | ||||||
| DQN_FILE_SCOPE char *DqnChar_GetNextLine (char *ptr, i32 *lineLength); |  | ||||||
| 
 |  | ||||||
| // #DqnStr API
 |  | ||||||
| // =================================================================================================
 |  | ||||||
| // numBytesToCompare: If -1, cmp runs until \0 is encountered.
 |  | ||||||
| // return:            0 if equal. 0 < if a is before b, > 0 if a is after b
 |  | ||||||
| DQN_FILE_SCOPE i32   DqnStr_Cmp               (char const *const a, char const *const b, i32 numBytesToCompare = -1, bool ignoreCase = false); |  | ||||||
| 
 |  | ||||||
| // strLen: Len of string, if -1, StrLen is used.
 |  | ||||||
| // return: Pointer in str to the last slash, if none then the original string.
 |  | ||||||
| DQN_FILE_SCOPE char *DqnStr_GetPtrToLastSlash (char const *str, i32 strLen = -1); |  | ||||||
| 
 |  | ||||||
| // return: String length not including the nullptr terminator. 0 if invalid args.
 |  | ||||||
| DQN_FILE_SCOPE i32   DqnStr_Len               (char const *const a); |  | ||||||
| DQN_FILE_SCOPE i32   DqnStr_LenUTF8           (u32 const *const a, i32 *const lenInBytes = nullptr); |  | ||||||
| 
 |  | ||||||
| // return: String length starting from a, up to and not including the first delimiter character.
 |  | ||||||
| DQN_FILE_SCOPE i32   DqnStr_LenDelimitWith    (char *const a, char const delimiter); |  | ||||||
| 
 |  | ||||||
| // return: The dest argument, nullptr if args invalid (i.e. nullptr pointers or numChars < 0)
 |  | ||||||
| DQN_FILE_SCOPE char *DqnStr_Copy              (char *const dest, char const *const src, i32 const numChars); |  | ||||||
| DQN_FILE_SCOPE void  DqnStr_Reverse           (char *const buf, i32 const bufSize); |  | ||||||
| 
 |  | ||||||
| // return: Number of bytes in codepoint, 0 if *a becomes invalid or end of stream.
 |  | ||||||
| DQN_FILE_SCOPE i32   DqnStr_ReadUTF8Codepoint (u32 const *const a, u32 *outCodepoint); |  | ||||||
| 
 |  | ||||||
| // return: The offset into the src to first char of the found string. Returns -1 if not found
 |  | ||||||
| DQN_FILE_SCOPE i32   DqnStr_FindFirstOccurence(char const *src, i32 const srcLen, char const *find, i32 const findLen, bool ignoreCase = false); |  | ||||||
| 
 |  | ||||||
| // return: Helper function that returns the pointer to the first occurence, nullptr if not found.
 |  | ||||||
| DQN_FILE_SCOPE char *DqnStr_GetFirstOccurence (char const *src, i32 const srcLen, char const *find, i32 const findLen, bool ignoreCase = false); |  | ||||||
| DQN_FILE_SCOPE bool  DqnStr_HasSubstring      (char const *src, i32 const srcLen, char const *find, i32 const findLen, bool ignoreCase = false); |  | ||||||
| 
 |  | ||||||
| #define DQN_32BIT_NUM_MAX_STR_SIZE 11 |  | ||||||
| #define DQN_64BIT_NUM_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.
 |  | ||||||
| DQN_FILE_SCOPE i32 Dqn_I64ToStr(i64 const value, char *const buf, i32 const bufSize); |  | ||||||
| DQN_FILE_SCOPE i64 Dqn_StrToI64(char const *const buf, i64 const bufSize); |  | ||||||
| // WARNING: Not robust, precision errors and whatnot but good enough!
 |  | ||||||
| DQN_FILE_SCOPE f32 Dqn_StrToF32(char const *const buf, i64 const bufSize); |  | ||||||
| 
 |  | ||||||
| // Both return the number of bytes read, return 0 if invalid codepoint or UTF8
 |  | ||||||
| DQN_FILE_SCOPE u32 Dqn_UCSToUTF8(u32 *const dest, u32 const character); |  | ||||||
| DQN_FILE_SCOPE u32 Dqn_UTF8ToUCS(u32 *const dest, u32 const character); |  | ||||||
| 
 |  | ||||||
| // #DqnWChar API
 |  | ||||||
| // =================================================================================================
 |  | ||||||
| // NOTE: See above for documentation
 |  | ||||||
| DQN_FILE_SCOPE bool     DqnWChar_IsDigit          (wchar_t const c); |  | ||||||
| DQN_FILE_SCOPE wchar_t  DqnWChar_ToLower          (wchar_t const c); |  | ||||||
| 
 |  | ||||||
| DQN_FILE_SCOPE wchar_t *DqnWChar_SkipWhitespace   (wchar_t *ptr); |  | ||||||
| DQN_FILE_SCOPE wchar_t *DqnWChar_FindLastChar     (wchar_t *ptr, const wchar_t ch, i32 len, u32 *const lenToChar); |  | ||||||
| DQN_FILE_SCOPE i32      DqnWChar_GetNextLine      (const wchar_t *ptr, i32 *lineLength); |  | ||||||
| 
 |  | ||||||
| DQN_FILE_SCOPE i32      DqnWStr_Cmp               (wchar_t const *const a, const wchar_t *const b); |  | ||||||
| DQN_FILE_SCOPE i32      DqnWStr_FindFirstOccurence(wchar_t const *const src, i32 const srcLen, wchar_t const *const find, i32 const findLen); |  | ||||||
| DQN_FILE_SCOPE bool     DqnWStr_HasSubstring      (wchar_t const *const src, i32 const srcLen, wchar_t const *const find, i32 const findLen); |  | ||||||
| DQN_FILE_SCOPE i32      DqnWStr_Len               (wchar_t const *const a); |  | ||||||
| DQN_FILE_SCOPE i32      DqnWStr_LenDelimitWith    (wchar_t const *const a, wchar_t const delimiter); |  | ||||||
| DQN_FILE_SCOPE void     DqnWStr_Reverse           (wchar_t *const buf, u32 const bufSize); |  | ||||||
| 
 |  | ||||||
| DQN_FILE_SCOPE i32      Dqn_WStrToI32             (wchar_t const *const buf, i32 const bufSize); |  | ||||||
| DQN_FILE_SCOPE i32      Dqn_I32ToWStr             (i32 value, wchar_t *buf, i32 bufSize); |  | ||||||
| 
 |  | ||||||
| // #DqnRnd API
 | // #DqnRnd API
 | ||||||
| // =================================================================================================
 | // =================================================================================================
 | ||||||
| // NOTE: Uses PCG (Permuted Congruential Generator)
 | // NOTE: Uses PCG (Permuted Congruential Generator)
 | ||||||
| @ -2863,7 +2872,7 @@ DQN_FILE_SCOPE void DqnLog(char *file, char const *const functionName, i32 const | |||||||
| 	#endif | 	#endif | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| DQN_FILE_SCOPE void DqnLog(char *file, char const *const functionName, i32 const lineNum, | DQN_FILE_SCOPE void DqnLogExpr(char *file, char const *const functionName, i32 const lineNum, | ||||||
|                            char const *const expr, char const *const msg, ...) |                            char const *const expr, char const *const msg, ...) | ||||||
| { | { | ||||||
| 	auto fileLen = DqnStr_Len(file); | 	auto fileLen = DqnStr_Len(file); | ||||||
| @ -4808,7 +4817,7 @@ DQN_FILE_SCOPE i32 DqnStr_ReadUTF8Codepoint(const u32 *const a, u32 *outCodepoin | |||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| DQN_FILE_SCOPE void DqnStr_Reverse(char *const buf, const i32 bufSize) | DQN_FILE_SCOPE void DqnStr_Reverse(char *const buf, i32 bufSize) | ||||||
| { | { | ||||||
| 	if (!buf) return; | 	if (!buf) return; | ||||||
| 	i32 mid = bufSize / 2; | 	i32 mid = bufSize / 2; | ||||||
| @ -4821,8 +4830,23 @@ DQN_FILE_SCOPE void DqnStr_Reverse(char *const buf, const i32 bufSize) | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| DQN_FILE_SCOPE i32 DqnStr_FindFirstOccurence(char const *src, i32 const srcLen, | DQN_FILE_SCOPE bool DqnStr_EndsWith(char const *src, i32 srcLen, char const *find, i32 findLen, | ||||||
|                                              char const *find, i32 const findLen, bool ignoreCase) |                                     bool ignoreCase) | ||||||
|  | { | ||||||
|  | 	if (!src || !find || findLen < 0 || srcLen < 0) return false; | ||||||
|  | 
 | ||||||
|  | 	if (srcLen < findLen) | ||||||
|  | 		return false; | ||||||
|  | 
 | ||||||
|  | 	char const *srcEnd       = src + (srcLen - 1); | ||||||
|  | 	char const *checkSrcFrom = srcEnd - findLen; | ||||||
|  | 
 | ||||||
|  | 	bool result = (DqnStr_Cmp(checkSrcFrom, find, findLen, ignoreCase) == 0); | ||||||
|  | 	return result; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | DQN_FILE_SCOPE i32 DqnStr_FindFirstOccurence(char const *src, i32 srcLen, | ||||||
|  |                                              char const *find, i32 findLen, bool ignoreCase) | ||||||
| { | { | ||||||
| 	if (!src || !find)               return -1; | 	if (!src || !find)               return -1; | ||||||
| 	if (srcLen == 0 || findLen == 0) return -1; | 	if (srcLen == 0 || findLen == 0) return -1; | ||||||
| @ -4848,8 +4872,8 @@ DQN_FILE_SCOPE i32 DqnStr_FindFirstOccurence(char const *src, i32 const srcLen, | |||||||
| 	return -1; | 	return -1; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| DQN_FILE_SCOPE char *DqnStr_GetFirstOccurence(char const *src, i32 const srcLen, char const *find, | DQN_FILE_SCOPE char *DqnStr_GetFirstOccurence(char const *src, i32 srcLen, char const *find, | ||||||
|                                               i32 const findLen, bool ignoreCase) |                                               i32 findLen, bool ignoreCase) | ||||||
| { | { | ||||||
| 	i32 offset = DqnStr_FindFirstOccurence(src, srcLen, find, findLen, ignoreCase); | 	i32 offset = DqnStr_FindFirstOccurence(src, srcLen, find, findLen, ignoreCase); | ||||||
| 	if (offset == -1) return nullptr; | 	if (offset == -1) return nullptr; | ||||||
| @ -4858,8 +4882,8 @@ DQN_FILE_SCOPE char *DqnStr_GetFirstOccurence(char const *src, i32 const srcLen, | |||||||
| 	return result; | 	return result; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| DQN_FILE_SCOPE bool DqnStr_HasSubstring(char const *src, i32 const srcLen, | DQN_FILE_SCOPE bool DqnStr_HasSubstring(char const *src, i32 srcLen, | ||||||
|                                         char const *find, i32 const findLen, bool ignoreCase) |                                         char const *find, i32 findLen, bool ignoreCase) | ||||||
| { | { | ||||||
| 	if (DqnStr_FindFirstOccurence(src, srcLen, find, findLen, ignoreCase) == -1) | 	if (DqnStr_FindFirstOccurence(src, srcLen, find, findLen, ignoreCase) == -1) | ||||||
| 		return false; | 		return false; | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user