diff --git a/dqn.h b/dqn.h index 38c1e88..7563edc 100644 --- a/dqn.h +++ b/dqn.h @@ -355,7 +355,7 @@ DQN_FILE_SCOPE DqnRect dqn_rect_move (DqnRect rect, DqnV2 shift); DQN_FILE_SCOPE bool dqn_rect_contains_p (DqnRect rect, DqnV2 p); //////////////////////////////////////////////////////////////////////////////// -// String Ops +// char String Operations //////////////////////////////////////////////////////////////////////////////// DQN_FILE_SCOPE char dqn_char_to_lower (char c); DQN_FILE_SCOPE char dqn_char_to_upper (char c); @@ -369,9 +369,6 @@ DQN_FILE_SCOPE i32 dqn_strlen (const char *a); DQN_FILE_SCOPE i32 dqn_strlen_delimit_with(const char *a, const char delimiter); DQN_FILE_SCOPE char *dqn_strncpy (char *dest, const char *src, i32 numChars); -DQN_FILE_SCOPE i32 dqn_wstrlen(const wchar_t *a); -DQN_FILE_SCOPE i32 dqn_wstrcmp(const wchar_t *a, const wchar_t *b); - #define DQN_I32_TO_STR_MAX_BUF_SIZE 11 DQN_FILE_SCOPE bool dqn_str_reverse (char *buf, const i32 bufSize); DQN_FILE_SCOPE bool dqn_str_has_substring(const char *const a, const i32 lenA, @@ -385,6 +382,20 @@ DQN_FILE_SCOPE i32 dqn_i32_to_str(i32 value, char *buf, i32 bufSize); DQN_FILE_SCOPE u32 dqn_ucs_to_utf8(u32 *dest, u32 character); DQN_FILE_SCOPE u32 dqn_utf8_to_ucs(u32 *dest, u32 character); +//////////////////////////////////////////////////////////////////////////////// +// wchar String Operations +//////////////////////////////////////////////////////////////////////////////// +DQN_FILE_SCOPE bool dqn_wchar_is_digit(const wchar_t c); +DQN_FILE_SCOPE wchar_t dqn_wchar_to_lower(const wchar_t c); + +DQN_FILE_SCOPE i32 dqn_wstrlen (const wchar_t *a); +DQN_FILE_SCOPE i32 dqn_wstrcmp (const wchar_t *a, const wchar_t *b); + +DQN_FILE_SCOPE bool dqn_wstr_reverse (wchar_t *buf, const i32 bufSize); + +DQN_FILE_SCOPE i32 dqn_wstr_to_i32 (const wchar_t *const buf, const i32 bufSize); +DQN_FILE_SCOPE i32 dqn_i32_to_wstr (i32 value, wchar_t *buf, i32 bufSize); + //////////////////////////////////////////////////////////////////////////////// // Win32 Specific //////////////////////////////////////////////////////////////////////////////// @@ -437,7 +448,7 @@ typedef struct DqnFile DQN_FILE_SCOPE bool dqn_file_open(const char *const path, DqnFile *const file, const u32 permissionFlags, const enum DqnFileAction action); -DQN_FILE_SCOPE bool dqn_file_open_wide(const wchar_t *const path, DqnFile *const file, +DQN_FILE_SCOPE bool dqn_file_openw(const wchar_t *const path, DqnFile *const file, const u32 permissionFlags, const enum DqnFileAction action); @@ -840,8 +851,7 @@ dqn_ini_property_add void dqn_ini_property_add( DqnIni* ini, int section, char const* name, int name_length, char const* value, int value_length ) -Adds a property with the specified name and value to the specified section, and -returns the index it was added at. There is no check done to see if a property +Adds a property with the specified name and value to the specified section, and returns the index it was added at. There is no check done to see if a property with the specified name already exists - multiple properties of the same name are allowed. `name_length` and `value_length` specifies the number of characters in `name` and `value`, which does not have to be zero-terminated. If @@ -1594,7 +1604,7 @@ DQN_FILE_SCOPE bool dqn_rect_contains_p(DqnRect rect, DqnV2 p) } //////////////////////////////////////////////////////////////////////////////// -// String Operations +// char String Operations //////////////////////////////////////////////////////////////////////////////// DQN_FILE_SCOPE char dqn_char_to_lower(char c) { @@ -1679,30 +1689,6 @@ DQN_FILE_SCOPE char *dqn_strncpy(char *dest, const char *src, i32 numChars) return dest; } -DQN_FILE_SCOPE i32 dqn_wstrlen(const wchar_t *a) -{ - i32 result = 0; - while (a && a[result]) result++; - return result; -} - -DQN_FILE_SCOPE i32 dqn_wstrcmp(const wchar_t *a, const wchar_t *b) -{ - if (!a && !b) return -1; - if (!a) return -1; - if (!b) return -1; - - while ((*a) == (*b)) - { - if (!(*a)) return 0; - a++; - b++; - } - - return (((*a) < (*b)) ? -1 : 1); -} - - DQN_FILE_SCOPE bool dqn_str_reverse(char *buf, const i32 bufSize) { if (!buf) return false; @@ -2013,6 +1999,137 @@ DQN_FILE_SCOPE u32 dqn_utf8_to_ucs(u32 *dest, u32 character) return 0; } +//////////////////////////////////////////////////////////////////////////////// +// wchar String Operations +//////////////////////////////////////////////////////////////////////////////// +DQN_FILE_SCOPE bool dqn_wchar_is_digit(const wchar_t c) +{ + if (c >= L'0' && c <= L'9') return true; + return false; +} + +DQN_FILE_SCOPE wchar_t dqn_wchar_to_lower(const wchar_t c) +{ + if (c >= L'A' && c <= L'Z') + { + i32 shiftOffset = L'a' - L'A'; + return (c + (wchar_t)shiftOffset); + } + + return c; +} + +DQN_FILE_SCOPE i32 dqn_wstrlen(const wchar_t *a) +{ + i32 result = 0; + while (a && a[result]) result++; + return result; +} + +DQN_FILE_SCOPE i32 dqn_wstrcmp(const wchar_t *a, const wchar_t *b) +{ + if (!a && !b) return -1; + if (!a) return -1; + if (!b) return -1; + + while ((*a) == (*b)) + { + if (!(*a)) return 0; + a++; + b++; + } + + return (((*a) < (*b)) ? -1 : 1); +} + +DQN_FILE_SCOPE bool dqn_wstr_reverse(wchar_t *buf, const i32 bufSize) +{ + if (!buf) return false; + i32 mid = bufSize / 2; + + for (i32 i = 0; i < mid; i++) + { + wchar_t tmp = buf[i]; + buf[i] = buf[(bufSize - 1) - i]; + buf[(bufSize - 1) - i] = tmp; + } + + return true; +} + +DQN_FILE_SCOPE i32 dqn_wstr_to_i32(const wchar_t *const buf, const i32 bufSize) +{ + if (!buf || bufSize == 0) return 0; + + i32 index = 0; + bool isNegative = false; + if (buf[index] == L'-' || buf[index] == L'+') + { + if (buf[index] == L'-') isNegative = true; + index++; + } + else if (!dqn_wchar_is_digit(buf[index])) + { + return 0; + } + + i32 result = 0; + for (i32 i = index; i < bufSize; i++) + { + if (dqn_wchar_is_digit(buf[i])) + { + result *= 10; + result += (buf[i] - L'0'); + } + else + { + break; + } + } + + if (isNegative) result *= -1; + + return result; +} + +DQN_FILE_SCOPE i32 dqn_i32_to_wstr(i32 value, wchar_t *buf, i32 bufSize) +{ + if (!buf || bufSize == 0) return 0; + + if (value == 0) + { + buf[0] = L'0'; + return 0; + } + + // NOTE(doyle): Max 32bit integer (+-)2147483647 + i32 charIndex = 0; + bool negative = false; + if (value < 0) negative = true; + + if (negative) buf[charIndex++] = L'-'; + + i32 val = DQN_ABS(value); + while (val != 0 && charIndex < bufSize) + { + i32 rem = val % 10; + buf[charIndex++] = (u8)rem + '0'; + val /= 10; + } + + // NOTE(doyle): If string is negative, we only want to reverse starting + // from the second character, so we don't put the negative sign at the end + if (negative) + { + dqn_wstr_reverse(buf + 1, charIndex - 1); + } + else + { + dqn_wstr_reverse(buf, charIndex); + } + + return charIndex; +} //////////////////////////////////////////////////////////////////////////////// // File Operations //////////////////////////////////////////////////////////////////////////////// @@ -2144,18 +2261,15 @@ FILE_SCOPE bool dqn_file_open_internal(const wchar_t *const path, } DQN_FILE_SCOPE -bool dqn_file_open_wide(const wchar_t *const path, DqnFile *const file, - const u32 permissionFlags, - const enum DqnFileAction action) +bool dqn_file_openw(const wchar_t *const path, DqnFile *const file, + const u32 permissionFlags, const enum DqnFileAction action) { if (!file || !path) return false; #ifdef DQN_WIN32 - dqn_file_open_internal(path, file, permissionFlags, action); + return dqn_file_open_internal(path, file, permissionFlags, action); #else return false; #endif - - return true; } DQN_FILE_SCOPE