mirror of
https://github.com/Mauler125/r5sdk.git
synced 2025-02-09 19:15:03 +01:00
219 lines
5.6 KiB
C++
219 lines
5.6 KiB
C++
#include "core/stdafx.h"
|
|
#include "tier1/strtools.h"
|
|
|
|
FORCEINLINE unsigned char tolower_fast(unsigned char c)
|
|
{
|
|
if ((c >= 'A') && (c <= 'Z'))
|
|
return c + ('a' - 'A');
|
|
return c;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Finds a string in another string with a case insensitive test
|
|
//-----------------------------------------------------------------------------
|
|
char const* V_stristr(char const* pStr, char const* pSearch)
|
|
{
|
|
AssertValidStringPtr(reinterpret_cast<const TCHAR*>(pStr));
|
|
AssertValidStringPtr(reinterpret_cast<const TCHAR*>(pSearch));
|
|
|
|
if (!pStr || !pSearch)
|
|
return 0;
|
|
|
|
char const* pLetter = pStr;
|
|
|
|
// Check the entire string
|
|
while (*pLetter != 0)
|
|
{
|
|
// Skip over non-matches
|
|
if (tolower_fast((unsigned char)*pLetter) == tolower_fast((unsigned char)*pSearch))
|
|
{
|
|
// Check for match
|
|
char const* pMatch = pLetter + 1;
|
|
char const* pTest = pSearch + 1;
|
|
while (*pTest != 0)
|
|
{
|
|
// We've run off the end; don't bother.
|
|
if (*pMatch == 0)
|
|
return 0;
|
|
|
|
if (tolower_fast((unsigned char)*pMatch) != tolower_fast((unsigned char)*pTest))
|
|
break;
|
|
|
|
++pMatch;
|
|
++pTest;
|
|
}
|
|
|
|
// Found a match!
|
|
if (*pTest == 0)
|
|
return pLetter;
|
|
}
|
|
|
|
++pLetter;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
char* V_stristr(char* pStr, char const* pSearch)
|
|
{
|
|
AssertValidStringPtr(reinterpret_cast<const TCHAR*>(pStr));
|
|
AssertValidStringPtr(reinterpret_cast<const TCHAR*>(pSearch));
|
|
|
|
return (char*)V_stristr((char const*)pStr, pSearch);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Finds a string in another string with a case insensitive test w/ length validation
|
|
//-----------------------------------------------------------------------------
|
|
const char* V_strnistr(const char* pStr, const char* pSearch, int64_t n)
|
|
{
|
|
Assert(pStr);
|
|
Assert(pSearch);
|
|
if (!pStr || !pSearch)
|
|
return 0;
|
|
|
|
const char* pLetter = pStr;
|
|
|
|
// Check the entire string
|
|
while (*pLetter != 0)
|
|
{
|
|
if (n <= 0)
|
|
return 0;
|
|
|
|
// Skip over non-matches
|
|
if (FastASCIIToLower(*pLetter) == FastASCIIToLower(*pSearch))
|
|
{
|
|
int n1 = n - 1;
|
|
|
|
// Check for match
|
|
const char* pMatch = pLetter + 1;
|
|
const char* pTest = pSearch + 1;
|
|
while (*pTest != 0)
|
|
{
|
|
if (n1 <= 0)
|
|
return 0;
|
|
|
|
// We've run off the end; don't bother.
|
|
if (*pMatch == 0)
|
|
return 0;
|
|
|
|
if (FastASCIIToLower(*pMatch) != FastASCIIToLower(*pTest))
|
|
break;
|
|
|
|
++pMatch;
|
|
++pTest;
|
|
--n1;
|
|
}
|
|
|
|
// Found a match!
|
|
if (*pTest == 0)
|
|
return pLetter;
|
|
}
|
|
|
|
++pLetter;
|
|
--n;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
const char* V_strnchr(const char* pStr, char c, int64_t n)
|
|
{
|
|
const char* pLetter = pStr;
|
|
const char* pLast = pStr + n;
|
|
|
|
// Check the entire string
|
|
while ((pLetter < pLast) && (*pLetter != 0))
|
|
{
|
|
if (*pLetter == c)
|
|
return pLetter;
|
|
++pLetter;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
bool V_isspace(int c)
|
|
{
|
|
// The standard white-space characters are the following: space, tab, carriage-return, newline, vertical tab, and form-feed. In the C locale, V_isspace() returns true only for the standard white-space characters.
|
|
//return c == ' ' || c == 9 /*horizontal tab*/ || c == '\r' || c == '\n' || c == 11 /*vertical tab*/ || c == '\f';
|
|
// codes of whitespace symbols: 9 HT, 10 \n, 11 VT, 12 form feed, 13 \r, 32 space
|
|
|
|
// easy to understand version, validated:
|
|
// return ((1 << (c-1)) & 0x80001F00) != 0 && ((c-1)&0xE0) == 0;
|
|
|
|
// 5% faster on Core i7, 35% faster on Xbox360, no branches, validated:
|
|
#ifdef _X360
|
|
return ((1 << (c - 1)) & 0x80001F00 & ~(-int((c - 1) & 0xE0))) != 0;
|
|
#else
|
|
// this is 11% faster on Core i7 than the previous, VC2005 compiler generates a seemingly unbalanced search tree that's faster
|
|
switch (c)
|
|
{
|
|
case ' ':
|
|
case 9:
|
|
case '\r':
|
|
case '\n':
|
|
case 11:
|
|
case '\f':
|
|
return true;
|
|
default:
|
|
return false;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: Converts a UTF8 string into a unicode string
|
|
//-----------------------------------------------------------------------------
|
|
int V_UTF8ToUnicode(const char* pUTF8, wchar_t* pwchDest, int cubDestSizeInBytes)
|
|
{
|
|
Assert(cubDestSizeInBytes >= sizeof(*pwchDest));
|
|
pwchDest[0] = 0;
|
|
if (!pUTF8)
|
|
return 0;
|
|
#ifdef _WIN32
|
|
int cchResult = MultiByteToWideChar(CP_UTF8, 0, pUTF8, -1, pwchDest, cubDestSizeInBytes / sizeof(wchar_t));
|
|
#elif POSIX
|
|
int cchResult = mbstowcs(pwchDest, pUTF8, cubDestSizeInBytes / sizeof(wchar_t));
|
|
#endif
|
|
pwchDest[(cubDestSizeInBytes / sizeof(wchar_t)) - 1] = 0;
|
|
return cchResult;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: Converts a unicode string into a UTF8 (standard) string
|
|
//-----------------------------------------------------------------------------
|
|
int V_UnicodeToUTF8(const wchar_t* pUnicode, char* pUTF8, int cubDestSizeInBytes)
|
|
{
|
|
if (cubDestSizeInBytes > 0)
|
|
pUTF8[0] = 0;
|
|
|
|
#ifdef _WIN32
|
|
int cchResult = WideCharToMultiByte(CP_UTF8, 0, pUnicode, -1, pUTF8, cubDestSizeInBytes, NULL, NULL);
|
|
#elif POSIX
|
|
int cchResult = 0;
|
|
if (pUnicode && pUTF8)
|
|
cchResult = wcstombs(pUTF8, pUnicode, cubDestSizeInBytes);
|
|
#endif
|
|
|
|
if (cubDestSizeInBytes > 0)
|
|
pUTF8[cubDestSizeInBytes - 1] = 0;
|
|
|
|
return cchResult;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: Changes all '/' or '\' characters into separator
|
|
// Input : *pName -
|
|
// cSeparator -
|
|
//-----------------------------------------------------------------------------
|
|
void V_FixSlashes(char* pName, char cSeperator /* = CORRECT_PATH_SEPARATOR */)
|
|
{
|
|
while (*pName)
|
|
{
|
|
if (*pName == INCORRECT_PATH_SEPARATOR || *pName == CORRECT_PATH_SEPARATOR)
|
|
{
|
|
*pName = cSeperator;
|
|
}
|
|
pName++;
|
|
}
|
|
} |