You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
447 lines
16 KiB
447 lines
16 KiB
/*==LICENSE==* |
|
|
|
CyanWorlds.com Engine - MMOG client, server and tools |
|
Copyright (C) 2011 Cyan Worlds, Inc. |
|
|
|
This program is free software: you can redistribute it and/or modify |
|
it under the terms of the GNU General Public License as published by |
|
the Free Software Foundation, either version 3 of the License, or |
|
(at your option) any later version. |
|
|
|
This program is distributed in the hope that it will be useful, |
|
but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
GNU General Public License for more details. |
|
|
|
You should have received a copy of the GNU General Public License |
|
along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
|
|
Additional permissions under GNU GPL version 3 section 7 |
|
|
|
If you modify this Program, or any covered work, by linking or |
|
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK, |
|
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent |
|
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK |
|
(or a modified version of those libraries), |
|
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA, |
|
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG |
|
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the |
|
licensors of this Program grant you additional |
|
permission to convey the resulting work. Corresponding Source for a |
|
non-source form of such a combination shall include the source code for |
|
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered |
|
work. |
|
|
|
You can contact Cyan Worlds, Inc. by email legal@cyan.com |
|
or by snail mail at: |
|
Cyan Worlds, Inc. |
|
14617 N Newport Hwy |
|
Mead, WA 99021 |
|
|
|
*==LICENSE==*/ |
|
/***************************************************************************** |
|
* |
|
* $/Plasma20/Sources/Plasma/NucleusLib/pnUtils/Private/pnUtStr.cpp |
|
* |
|
***/ |
|
|
|
#include "pnUtStr.h" |
|
|
|
|
|
/***************************************************************************** |
|
* |
|
* Private data |
|
* |
|
***/ |
|
|
|
// These random values were generated by the radioactive decay based |
|
// random number generator at www.fourmilab.ch |
|
static uint32_t s_hashValue[] = { |
|
0xc30d2a72, 0x15efaec1, 0xd250c7d9, 0xaf3c60a8, |
|
0x9608ae8f, 0x452c0e11, 0xb6840ffd, 0x3e36c913, |
|
0x2864eace, 0x9b0a17d6, 0x108da74b, 0xf2c479c1, |
|
0x8b4dd597, 0x97199bc0, 0x621f0cce, 0x1658553e, |
|
}; |
|
|
|
|
|
/**************************************************************************** |
|
* |
|
* Internal functions |
|
* |
|
***/ |
|
//=========================================================================== |
|
template<class chartype> |
|
static unsigned IStrLen (const chartype str[]) { |
|
unsigned chars = 0; |
|
for (; *str++; ++chars) |
|
NULL_STMT; |
|
return chars; |
|
} |
|
|
|
//=========================================================================== |
|
template<class chartype> |
|
static void IStrCopy (chartype * dest, const chartype source[], unsigned chars) { |
|
while ((chars > 1) && ((*dest = *source++) != 0)) { |
|
--chars; |
|
++dest; |
|
} |
|
if (chars) |
|
*dest = 0; |
|
} |
|
|
|
//=========================================================================== |
|
template<class chartype> |
|
static chartype * IStrDup (const chartype str[]) { |
|
unsigned chars = IStrLen(str) + 1; |
|
chartype * buffer = (chartype *)malloc(chars * sizeof(chartype)); |
|
IStrCopy(buffer, str, chars); |
|
return buffer; |
|
} |
|
|
|
//=========================================================================== |
|
template<class chartype, class findchartype> |
|
static chartype * IStrChr (chartype * str, findchartype ch, unsigned chars) { |
|
for (; chars--; ++str) |
|
if (*str == ch) |
|
return str; |
|
else if (!*str) |
|
break; |
|
return nil; |
|
} |
|
|
|
//=========================================================================== |
|
template<typename chartype> |
|
static unsigned IStrPrintfValidate (chartype * dest, unsigned count, int result) { |
|
if (!count) |
|
return 0; |
|
ASSERT(result <= (int)count); |
|
if ((result < 0) || (result == (int)count)) { |
|
dest[count - 1] = 0; |
|
return count - 1; |
|
} |
|
else |
|
return (unsigned)result; |
|
} |
|
|
|
//=========================================================================== |
|
template<class chartype> |
|
static int IStrCmp (const chartype str1[], const chartype str2[], unsigned chars) { |
|
for (; chars--; ++str1, ++str2) { |
|
if (*str1 != *str2) |
|
return (*str1 > *str2) ? 1 : -1; |
|
if (!*str1) |
|
return 0; |
|
} |
|
return 0; |
|
} |
|
|
|
//=========================================================================== |
|
template<class chartype> |
|
static int IStrCmpI (const chartype str1[], const chartype str2[], unsigned chars) { |
|
while (chars--) { |
|
chartype ch1 = CharLowerFast(*str1++); |
|
chartype ch2 = CharLowerFast(*str2++); |
|
if (ch1 != ch2) |
|
return (ch1 > ch2) ? 1 : -1; |
|
if (!ch1) |
|
return 0; |
|
} |
|
return 0; |
|
} |
|
|
|
//=========================================================================== |
|
template<class chartype> |
|
static uint32_t IStrHash (const chartype str[], unsigned chars) { |
|
uint32_t temp0 = 0xE2C15C9D; |
|
uint32_t temp1 = 0x2170A28A; |
|
uint32_t result = 0x325D1EAE; |
|
for (unsigned ch; chars-- && ((ch = (unsigned)*str) != 0); ++str) { |
|
temp0 = (temp0 << 3) ^ ch; |
|
temp1 += s_hashValue[temp0 & 0x0F]; |
|
result ^= temp0 + temp1; |
|
} |
|
return result; |
|
} |
|
|
|
//=========================================================================== |
|
template<class chartype> |
|
static uint32_t IStrHashI (const chartype str[], unsigned chars) { |
|
uint32_t temp0 = 0xE2C15C9D; |
|
uint32_t temp1 = 0x2170A28A; |
|
uint32_t result = 0x325D1EAE; |
|
for (unsigned ch; chars-- && ((ch = (unsigned)*str) != 0); ++str) { |
|
if ((ch >= 'a') && (ch <= 'z')) |
|
ch = ch + 'A' - 'a'; |
|
temp0 = (temp0 << 3) ^ ch; |
|
temp1 += s_hashValue[temp0 & 0x0F]; |
|
result ^= temp0 + temp1; |
|
} |
|
return result; |
|
} |
|
|
|
//=========================================================================== |
|
template<class chartype> |
|
static bool IStrTokenize (const chartype * source[], chartype * dest, unsigned chars, const chartype whitespace[], unsigned maxWhitespaceSkipCount) { |
|
|
|
// Skip past leading whitespace |
|
bool inQuotes = false; |
|
unsigned whitespaceSkipped = 0; |
|
while (**source && IStrChr(whitespace, **source, (unsigned)-1) && whitespaceSkipped < maxWhitespaceSkipCount) { |
|
inQuotes = (**source == '\"'); |
|
++*source; |
|
++whitespaceSkipped; |
|
if (inQuotes) |
|
break; |
|
} |
|
|
|
// Copy the token |
|
unsigned offset = 0; |
|
while (**source && |
|
((inQuotes && (**source != '\"')) || !IStrChr(whitespace, **source, (unsigned)-1))) { |
|
if (offset + 1 < chars) |
|
dest[offset++] = **source; |
|
++*source; |
|
} |
|
|
|
// Skip past the terminating quote |
|
if (inQuotes && (**source == '\"')) |
|
++*source; |
|
|
|
// Null terminate the destination buffer |
|
if (chars) { |
|
ASSERT(offset < chars); |
|
dest[offset] = 0; |
|
} |
|
|
|
// Upon return, 'source' is guaranteed to point to the first character |
|
// following the returned token (and following any closing quotes) |
|
|
|
return (offset || inQuotes); |
|
} |
|
|
|
//=========================================================================== |
|
template<class chartype> |
|
static bool IStrTokenize (const chartype * source[], ARRAY(chartype) * destArray, const chartype whitespace[], unsigned maxWhitespaceSkipCount) { |
|
|
|
// Verify that the destination array is empty |
|
ASSERT(!destArray->Count()); |
|
|
|
// Skip past leading whitespace |
|
bool inQuotes = false; |
|
unsigned whitespaceSkipped = 0; |
|
while (**source && IStrChr(whitespace, **source, (unsigned)-1) && whitespaceSkipped < maxWhitespaceSkipCount) { |
|
inQuotes = (**source == '\"'); |
|
++*source; |
|
++whitespaceSkipped; |
|
if (inQuotes) |
|
break; |
|
} |
|
|
|
// Copy the token |
|
bool added = false; |
|
while (**source && |
|
((inQuotes && (**source != '\"')) || !IStrChr(whitespace, **source, (unsigned)-1))) { |
|
destArray->Add(**source); |
|
added = true; |
|
++*source; |
|
} |
|
|
|
// Skip past the terminating quote |
|
if (inQuotes && (**source == '\"')) |
|
++*source; |
|
|
|
// Null terminate the destination array |
|
destArray->Add(0); |
|
|
|
// Upon return, 'source' is guaranteed to point to the first character |
|
// following the returned token (and following any closing quotes) |
|
|
|
return (added || inQuotes); |
|
} |
|
|
|
|
|
/**************************************************************************** |
|
* |
|
* Exported functions |
|
* |
|
***/ |
|
|
|
//=========================================================================== |
|
char * StrDup (const char str[]) { |
|
return IStrDup(str); |
|
} |
|
|
|
//=========================================================================== |
|
wchar_t * StrDup (const wchar_t str[]) { |
|
return IStrDup(str); |
|
} |
|
|
|
//=========================================================================== |
|
char * StrChr (char * str, char ch, unsigned chars) { |
|
return IStrChr(str, ch, chars); |
|
} |
|
|
|
//=========================================================================== |
|
wchar_t * StrChr (wchar_t * str, wchar_t ch, unsigned chars) { |
|
return IStrChr(str, ch, chars); |
|
} |
|
|
|
//=========================================================================== |
|
const char * StrChr (const char str[], char ch, unsigned chars) { |
|
return IStrChr(str, ch, chars); |
|
} |
|
|
|
//=========================================================================== |
|
const wchar_t * StrChr (const wchar_t str[], wchar_t ch, unsigned chars) { |
|
return IStrChr(str, ch, chars); |
|
} |
|
|
|
//=========================================================================== |
|
unsigned StrPrintf (char * dest, unsigned count, const char format[], ...) { |
|
va_list argList; |
|
va_start(argList, format); |
|
int result = hsVsnprintf((char *)dest, count, (const char *)format, argList); |
|
va_end(argList); |
|
return IStrPrintfValidate(dest, count, result); |
|
} |
|
|
|
//=========================================================================== |
|
unsigned StrPrintf (wchar_t * dest, unsigned count, const wchar_t format[], ...) { |
|
va_list argList; |
|
va_start(argList, format); |
|
int result = hsVsnwprintf(dest, count, format, argList); |
|
va_end(argList); |
|
return IStrPrintfValidate(dest, count, result); |
|
} |
|
|
|
//=========================================================================== |
|
unsigned StrPrintfV (char * dest, unsigned count, const char format[], va_list args) { |
|
int result = hsVsnprintf(dest, count, format, args); |
|
return IStrPrintfValidate(dest, count, result); |
|
} |
|
|
|
//=========================================================================== |
|
unsigned StrPrintfV (wchar_t * dest, unsigned count, const wchar_t format[], va_list args) { |
|
int result = hsVsnwprintf(dest, count, format, args); |
|
return IStrPrintfValidate(dest, count, result); |
|
} |
|
|
|
//=========================================================================== |
|
int StrCmp (const char str1[], const char str2[], unsigned chars) { |
|
return IStrCmp(str1, str2, chars); |
|
} |
|
|
|
//=========================================================================== |
|
int StrCmp (const wchar_t str1[], const wchar_t str2[], unsigned chars) { |
|
return IStrCmp(str1, str2, chars); |
|
} |
|
|
|
//=========================================================================== |
|
int StrCmpI (const char str1[], const char str2[], unsigned chars) { |
|
return IStrCmpI(str1, str2, chars); |
|
} |
|
|
|
//=========================================================================== |
|
int StrCmpI (const wchar_t str1[], const wchar_t str2[], unsigned chars) { |
|
return IStrCmpI(str1, str2, chars); |
|
} |
|
|
|
//=========================================================================== |
|
void StrCopy (char * dest, const char source[], unsigned chars) { |
|
IStrCopy(dest, source, chars); |
|
} |
|
|
|
//=========================================================================== |
|
void StrCopy (wchar_t * dest, const wchar_t source[], unsigned chars) { |
|
IStrCopy(dest, source, chars); |
|
} |
|
|
|
//=========================================================================== |
|
unsigned StrLen (const char str[]) { |
|
return IStrLen(str); |
|
} |
|
|
|
//=========================================================================== |
|
unsigned StrLen (const wchar_t str[]) { |
|
return IStrLen(str); |
|
} |
|
|
|
//=========================================================================== |
|
float StrToFloat (const char source[], const char ** endptr) { |
|
return (float) strtod(source, const_cast<char **>(endptr)); |
|
} |
|
|
|
//=========================================================================== |
|
float StrToFloat (const wchar_t source[], const wchar_t ** endptr) { |
|
return (float) wcstod(source, const_cast<wchar_t **>(endptr)); |
|
} |
|
|
|
//=========================================================================== |
|
int StrToInt (const char source[], const char ** endptr) { |
|
return strtol(source, const_cast<char **>(endptr), 0); |
|
} |
|
|
|
//=========================================================================== |
|
int StrToInt (const wchar_t source[], const wchar_t ** endptr) { |
|
return wcstol(source, const_cast<wchar_t **>(endptr), 0); |
|
} |
|
|
|
//=========================================================================== |
|
unsigned StrToUnsigned (char source[], char ** endptr, int radix) { |
|
return strtoul(source, const_cast<char **>(endptr), radix); |
|
} |
|
|
|
//=========================================================================== |
|
unsigned StrToUnsigned (wchar_t source[], wchar_t ** endptr, int radix) { |
|
return wcstoul(source, const_cast<wchar_t **>(endptr), radix); |
|
} |
|
|
|
//=========================================================================== |
|
unsigned StrToUnsigned (const char source[], const char ** endptr, int radix) { |
|
return strtoul(source, const_cast<char **>(endptr), radix); |
|
} |
|
|
|
//=========================================================================== |
|
unsigned StrToUnsigned (const wchar_t source[], const wchar_t ** endptr, int radix) { |
|
return wcstoul(source, const_cast<wchar_t **>(endptr), radix); |
|
} |
|
|
|
//=========================================================================== |
|
uint32_t StrHash (const char str[], unsigned chars) { |
|
return IStrHash(str, chars); |
|
} |
|
|
|
//=========================================================================== |
|
uint32_t StrHash (const wchar_t str[], unsigned chars) { |
|
return IStrHash(str, chars); |
|
} |
|
|
|
//=========================================================================== |
|
uint32_t StrHashI (const char str[], unsigned chars) { |
|
return IStrHashI(str, chars); |
|
} |
|
|
|
//=========================================================================== |
|
uint32_t StrHashI (const wchar_t str[], unsigned chars) { |
|
return IStrHashI(str, chars); |
|
} |
|
|
|
//=========================================================================== |
|
bool StrTokenize (const char * source[], char * dest, unsigned chars, const char whitespace[], unsigned maxWhitespaceSkipCount) { |
|
return IStrTokenize(source, dest, chars, whitespace, maxWhitespaceSkipCount); |
|
} |
|
|
|
//=========================================================================== |
|
bool StrTokenize (const wchar_t * source[], wchar_t * dest, unsigned chars, const wchar_t whitespace[], unsigned maxWhitespaceSkipCount) { |
|
return IStrTokenize(source, dest, chars, whitespace, maxWhitespaceSkipCount); |
|
} |
|
|
|
//=========================================================================== |
|
bool StrTokenize (const char * source[], ARRAY(char) * destArray, const char whitespace[], unsigned maxWhitespaceSkipCount) { |
|
return IStrTokenize(source, destArray, whitespace, maxWhitespaceSkipCount); |
|
} |
|
|
|
//=========================================================================== |
|
bool StrTokenize (const wchar_t * source[], ARRAY(wchar_t) * destArray, const wchar_t whitespace[], unsigned maxWhitespaceSkipCount) { |
|
return IStrTokenize(source, destArray, whitespace, maxWhitespaceSkipCount); |
|
}
|
|
|