diff --git a/lib/linux64/tier1.a b/lib/linux64/tier1.a index 46b752f5..2a80285f 100644 Binary files a/lib/linux64/tier1.a and b/lib/linux64/tier1.a differ diff --git a/lib/public/win64/tier1.lib b/lib/public/win64/tier1.lib index 62b46d56..48c1988a 100644 Binary files a/lib/public/win64/tier1.lib and b/lib/public/win64/tier1.lib differ diff --git a/linux_sdk/Makefile.tier1 b/linux_sdk/Makefile.tier1 index b8960c24..e29a3ecb 100644 --- a/linux_sdk/Makefile.tier1 +++ b/linux_sdk/Makefile.tier1 @@ -33,7 +33,6 @@ LIB_OBJS= \ $(LIB_OBJ_DIR)/commandbuffer.o \ $(LIB_OBJ_DIR)/generichash.o \ $(LIB_OBJ_DIR)/rangecheckedvar.o \ - $(LIB_OBJ_DIR)/strtools.o \ $(LIB_OBJ_DIR)/tier1.o \ $(LIB_OBJ_DIR)/utlbufferutil.o \ diff --git a/public/tier1/strtools.h b/public/tier1/strtools.h index 7a34b6c4..8eefa52d 100644 --- a/public/tier1/strtools.h +++ b/public/tier1/strtools.h @@ -30,6 +30,10 @@ class Vector4D; class Quaternion; class Color; class QAngle; +class CUtlString; + +template< class T, class I> class CUtlMemory; +template< class T, class A> class CUtlVector; abstract_class IParsingErrorListener { @@ -47,24 +51,13 @@ abstract_class IParsingErrorListener #define PARSING_FLAG_USE_BASE_AUTO (1 << 7) // Use auto detection of a number base when parsing (uses https://en.cppreference.com/w/cpp/string/basic_string/stol under the hood, so same base rules applies) #define PARSING_FLAG_USE_BASE_16 (1 << 8) // Use base of 16 when parsing -// 3d memcpy. Copy (up-to) 3 dimensional data with arbitrary source and destination -// strides. Optimizes to just a single memcpy when possible. For 2d data, set numslices to 1. -void CopyMemory3D( void *pDestAdr, void const *pSrcAdr, - int nNumCols, int nNumRows, int nNumSlices, // dimensions of copy - int nSrcBytesPerRow, int nSrcBytesPerSlice, // strides for source. - int nDestBytesPerRow, int nDestBytesPerSlice // strides for dest - ); - - -template< class T, class I > class CUtlMemory; -template< class T, class A > class CUtlVector; - // Unicode string conversion policies - what to do if an illegal sequence is encountered enum EStringConvertErrorPolicy { _STRINGCONVERTFLAG_SKIP = 1, _STRINGCONVERTFLAG_FAIL = 2, _STRINGCONVERTFLAG_ASSERT = 4, + _STRINGCONVERTFLAG_UNK001 = 8, STRINGCONVERT_REPLACE = 0, STRINGCONVERT_SKIP = _STRINGCONVERTFLAG_SKIP, @@ -78,68 +71,166 @@ enum EStringConvertErrorPolicy //----------------------------------------------------------------------------- // Portable versions of standard string functions //----------------------------------------------------------------------------- -void _V_memset ( void *dest, int fill, int count ); -void _V_memcpy ( void *dest, const void *src, int count ); -void _V_memmove ( void *dest, const void *src, int count ); -int _V_memcmp ( const void *m1, const void *m2, int count ); -int _V_strlen ( const char *str ); -void _V_strcpy ( char *dest, const char *src ); -char* _V_strrchr ( const char *s, char c ); -int _V_strcmp ( const char *s1, const char *s2 ); -int _V_wcscmp ( const wchar_t *s1, const wchar_t *s2 ); -int _V_stricmp ( const char *s1, const char *s2 ); -char* _V_strstr ( const char *s1, const char *search ); -char* _V_strupr ( char *start ); -char* _V_strlower ( char *start ); -int _V_wcslen ( const wchar_t *pwch ); +PLATFORM_INTERFACE void V_tier0_memset( void *dest, int fill, size_t count ); +PLATFORM_INTERFACE void V_tier0_memcpy( void *dest, const void *src, size_t count ); +PLATFORM_INTERFACE void V_tier0_memmove( void *dest, const void *src, size_t count ); +PLATFORM_INTERFACE int V_tier0_memcmp( const void *m1, const void *m2, size_t count ); -#ifdef POSIX -inline char *strupr( char *start ) +PLATFORM_INTERFACE int V_tier0_strlen( const char *str ); +PLATFORM_INTERFACE int V_tier0_strlen16( const char16_t *str ); +PLATFORM_INTERFACE int V_tier0_strlen32( const char32_t *str ); +PLATFORM_INTERFACE int V_tier0_wcslen( const wchar_t *str ); + +PLATFORM_INTERFACE void V_tier0_strcpy( char *dest, const char *src ); +PLATFORM_INTERFACE void _V_strncpy( char *pDest, const char *pSrc, int maxLen ); +PLATFORM_INTERFACE void V_tier0_strcpy32( char32_t *dest, const char32_t *src ); +PLATFORM_INTERFACE void _V_strncpy32_bytes( char32_t *pDest, const char32_t *pSrc, int bytes ); +PLATFORM_INTERFACE void V_tier0_wcscpy( wchar_t *dest, const wchar_t *src ); +PLATFORM_INTERFACE void _V_wcsncpy_bytes( wchar_t *pDest, const wchar_t *pSrc, int bytes ); + +PLATFORM_INTERFACE char * V_tier0_strrchr( const char *s, char c ); +PLATFORM_INTERFACE char * V_strnchr( const char *s, char c, int n ); +PLATFORM_INTERFACE char32_t * V_strchr32( const char32_t *s, char32_t c ); +PLATFORM_INTERFACE wchar_t * V_tier0_wcschr( const wchar_t *s, wchar_t c ); + +PLATFORM_INTERFACE int V_tier0_strcmp( const char *s1, const char *s2 ); +PLATFORM_INTERFACE int _V_strncmp( const char *s1, const char *s2, int n ); +PLATFORM_INTERFACE int V_strcmp32( const char32_t *s1, const char32_t *s2 ); +PLATFORM_INTERFACE int V_tier0_wcscmp( const wchar_t *s1, const wchar_t *s2 ); + +PLATFORM_INTERFACE int V_stricmp_fast( const char *s1, const char *s2 ); +PLATFORM_INTERFACE int V_stricmp_fast_NegativeForUnequal( const char *s1, const char *s2 ); +PLATFORM_INTERFACE int _V_strnicmp_fast( const char *s1, const char *s2, int n ); +PLATFORM_INTERFACE int V_wcsicmp( const wchar_t *s1, const wchar_t *s2 ); +PLATFORM_INTERFACE int V_wcsnicmp_cch( const wchar_t *s1, const wchar_t *s2, int symbols ); + +PLATFORM_INTERFACE char * V_tier0_strstr( const char *s1, const char *search ); +PLATFORM_INTERFACE char32_t * V_strstr32( const char32_t *s1, const char32_t *search ); + +PLATFORM_INTERFACE char * V_strupper_fast( char *start ); +PLATFORM_INTERFACE char32_t * V_towupper32( char32_t *start ); +PLATFORM_INTERFACE wchar_t * V_towupper( wchar_t *start ); + +PLATFORM_INTERFACE char * V_strlower_fast( char *start ); +PLATFORM_INTERFACE char32_t * V_towlower32( char32_t *start ); +PLATFORM_INTERFACE wchar_t * V_towlower( wchar_t *start ); + +PLATFORM_INTERFACE int V_atoi( const char *str ); +PLATFORM_INTERFACE int64 V_atoi64( const char *str ); +PLATFORM_INTERFACE uint64 V_atoui64( const char *str ); +PLATFORM_INTERFACE float V_atof( const char *str ); +PLATFORM_INTERFACE float V_atofloat32( const char *str ); +PLATFORM_INTERFACE double V_atofloat64( const char *str ); + +PLATFORM_INTERFACE double V_strtod( const char *str, char **endptr = NULL ); +PLATFORM_INTERFACE double V_wcstod( const wchar_t *str, wchar_t **endptr = NULL ); +PLATFORM_INTERFACE int64 V_strtoi64( const char *str, char **endptr = NULL ); +PLATFORM_INTERFACE int64 V_wcstoi64( const wchar_t *str, wchar_t **endptr = NULL ); +PLATFORM_INTERFACE uint64 V_strtoui64( const char *str, char **endptr = NULL ); +PLATFORM_INTERFACE uint64 V_wcstoui64( const wchar_t *str, wchar_t **endptr = NULL ); + +PLATFORM_INTERFACE char * V_strtok( const char *str, const char *delim ); + +PLATFORM_OVERLOAD const char * V_stristr_fast( const char *str, const char *search ); +PLATFORM_INTERFACE const char * _V_strnistr_fast( const char *str, const char *search, int n ); +PLATFORM_OVERLOAD const wchar_t *V_wcsistr( const wchar_t *str, const wchar_t *search ); + +PLATFORM_OVERLOAD int V_strnlen( const char *str, int n ); +PLATFORM_OVERLOAD int V_strnlen( const char32_t *str, int n ); +PLATFORM_OVERLOAD int V_strnlen( const wchar_t *str, int n ); + +PLATFORM_INTERFACE int _V_strcspn( const char *s1, const char *s2 ); + +#define COPY_ALL_CHARACTERS -1 +PLATFORM_INTERFACE char * _V_strncat( char *s1, const char *s2, size_t size, int max_chars_to_copy = COPY_ALL_CHARACTERS ); +inline void V_strcat( char *dest, const char *src, int cchDest ) { - char *str = start; - while( str && *str ) - { - *str = (char)toupper(*str); - str++; - } - return start; + _V_strncat( dest, src, cchDest, COPY_ALL_CHARACTERS ); } -inline char *strlwr( char *start ) +PLATFORM_INTERFACE int V_snprintf( char *pDest, int destLen, const char *pFormat, ... ) FMTFUNCTION( 3, 4 ); +PLATFORM_INTERFACE int V_snprintfcat( char *pDest, int destLen, const char *pFormat, ... ) FMTFUNCTION( 3, 4 ); +PLATFORM_INTERFACE int V_snwprintf_bytes( wchar_t *pDest, int bytes, const wchar_t *pFormat, ... ); +PLATFORM_INTERFACE int V_snwprintf_cch( wchar_t *pDest, int symbols, const wchar_t *pFormat, ... ); + +PLATFORM_INTERFACE int V_vsnprintf( char *pDest, int maxLenInCharacters, const char *pFormat, va_list params ); +PLATFORM_INTERFACE int V_vsnprintfcat( char *pDest, int maxLenInCharacters, const char *pFormat, va_list params ); +template int V_vsprintf_safe( char( &pDest )[maxLenInCharacters], const char *pFormat, va_list params ) { return V_vsnprintf( pDest, maxLenInCharacters, pFormat, params ); } + +PLATFORM_INTERFACE int V_vsnwprintf_cch( wchar_t *pDest, int maxLenInCharacters, const wchar_t *pFormat, va_list params ); +template int V_vswprintf_safe( char( &pDest )[maxLenInCharacters], const char *pFormat, va_list params ) { return V_vsnwprintf_cch( pDest, maxLenInCharacters, pFormat, params ); } + +PLATFORM_INTERFACE bool V_iswspace( wchar_t c ); +inline bool V_isspace( int c ) { - char *str = start; - while( str && *str ) - { - *str = (char)tolower(*str); - str++; - } - return start; + // 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 } -#endif // POSIX +// Short form remaps +#define V_memset(dest, fill, count) V_tier0_memset ((dest), (fill), (count)) +#define V_memcpy(dest, src, count) V_tier0_memcpy ((dest), (src), (count)) +#define V_memmove(dest, src, count) V_tier0_memmove ((dest), (src), (count)) +#define V_memcmp(m1, m2, count) V_tier0_memcmp ((m1), (m2), (count)) -// there are some users of these via tier1 templates in used in tier0. but tier0 can't depend on vstdlib which means in tier0 we always need the inlined ones -#if ( !defined( TIER0_DLL_EXPORT ) ) +#define V_strlen(str) V_tier0_strlen ((str)) +#define V_strlen16(str) V_tier0_strlen16 ((str)) +#define V_strlen32(str) V_tier0_strlen32 ((str)) +#define V_wcslen(str) V_tier0_wcslen ((str)) -#define V_memset(dest, fill, count) _V_memset ((dest), (fill), (count)) -#define V_memcpy(dest, src, count) _V_memcpy ((dest), (src), (count)) -#define V_memmove(dest, src, count) _V_memmove ((dest), (src), (count)) -#define V_memcmp(m1, m2, count) _V_memcmp ((m1), (m2), (count)) -#define V_strlen(str) _V_strlen ((str)) -#define V_strcpy(dest, src) _V_strcpy ((dest), (src)) -#define V_strrchr(s, c) _V_strrchr ((s), (c)) -#define V_strcmp(s1, s2) _V_strcmp ((s1), (s2)) -#define V_wcscmp(s1, s2) _V_wcscmp ((s1), (s2)) -#define V_stricmp(s1, s2 ) _V_stricmp ((s1), (s2) ) -#define V_strstr(s1, search ) _V_strstr ((s1), (search) ) -#define V_strupr(start) _V_strupr ((start)) -#define V_strlower(start) _V_strlower ((start)) -#define V_wcslen(pwch) _V_wcslen ((pwch)) +#define V_strcpy(dest, src) V_tier0_strcpy ((dest), (src)) +#define V_strncpy(dest, src, count) _V_strncpy ((dest), (src), (count)) +#define V_strcpy32(dest, src) V_tier0_strcpy32 ((dest), (src)) +#define V_strncpy32(dest, src, bytes) _V_strncpy32_bytes ((dest), (src), (bytes)) +#define V_wcscpy(dest, src) V_tier0_wcscpy ((dest), (src)) +#define V_wcsncpy(dest, src, bytes) _V_wcsncpy_bytes ((dest), (src), (bytes)) -// AM TODO: handle this for the rest (above and more) now exported by tier0 -PLATFORM_INTERFACE int V_stricmp_fast(const char* s1, const char* s2); +#define V_strrchr(s, c) V_tier0_strrchr ((s), (c)) +#define V_wcschr(s, c) V_tier0_wcschr ((s), (c)) -PLATFORM_INTERFACE int _V_strnicmp_fast(const char* s1, const char* s2, int n); +#define V_strcmp(s1, s2) V_tier0_strcmp ((s1), (s2)) +#define V_strncmp(s1, s2, count) _V_strncmp ((s1), (s2), (count)) +#define V_wcscmp(s1, s2) V_tier0_wcscmp ((s1), (s2)) + +#define V_stricmp(s1, s2) V_stricmp_fast ((s1), (s2) ) +#define V_stricmp_n(s1, s2) V_stricmp_fast_NegativeForUnequal((s1), (s2) ) +#define V_strnicmp(s1, s2, count) _V_strnicmp_fast ((s1), (s2), (count)) +#define V_wcsnicmp(s1, s2, symbols) V_wcsnicmp_cch ((s1), (s2), (symbols)) + +#define V_strstr(s1, search) V_tier0_strstr ((s1), (search)) + +#define V_strupper(start) V_strupper_fast ((start)) +#define V_strlower(start) V_strlower_fast ((start)) + +#define V_stristr(s1, search) V_stristr_fast ((s1), (start)) +#define V_strnistr(s1, search, count) _V_strnistr_fast ((s1), (start), (count)) + +#define V_strcspn(s1, s2) _V_strcspn ((s1), (s2)) + +#define V_strncat(s1, s2, count) _V_strncat ((s1), (s2), (count)) // Compares two strings with the support of wildcarding only for the first arg (includes '*' for multiple and '?' for single char usages) PLATFORM_INTERFACE int V_CompareNameWithWildcards(const char *wildcarded_string, const char *compare_to, bool case_sensitive = false); @@ -217,95 +308,20 @@ PLATFORM_INTERFACE float64 V_StringToFloat64Raw(const char *buf, float64 default // Parses string as a float32 value, if the parsing fails, default_value is returned, doesn't perform error checking/reporting PLATFORM_INTERFACE float32 V_StringToFloat32Raw(const char *buf, float32 default_value, bool *successful = NULL, char **remainder = NULL); -#else - -inline void V_memset (void *dest, int fill, int count) { memset( dest, fill, count ); } -inline void V_memcpy (void *dest, const void *src, int count) { memcpy( dest, src, count ); } -inline void V_memmove (void *dest, const void *src, int count) { memmove( dest, src, count ); } -inline int V_memcmp (const void *m1, const void *m2, int count){ return memcmp( m1, m2, count ); } -inline int V_strlen (const char *str) { return (int) strlen ( str ); } -inline void V_strcpy (char *dest, const char *src) { strcpy( dest, src ); } -inline int V_wcslen(const wchar_t *pwch) { return (int)wcslen(pwch); } -inline char* V_strrchr (const char *s, char c) { return (char*)strrchr( s, c ); } -inline int V_strcmp (const char *s1, const char *s2) { return strcmp( s1, s2 ); } -inline int V_wcscmp (const wchar_t *s1, const wchar_t *s2) { return wcscmp( s1, s2 ); } -inline int V_stricmp( const char *s1, const char *s2 ) { return stricmp( s1, s2 ); } -inline char* V_strstr( const char *s1, const char *search ) { return (char*)strstr( s1, search ); } -inline char* V_strupr (char *start) { return strupr( start ); } -inline char* V_strlower (char *start) { return strlwr( start ); } - -#endif - - -int V_strncmp (const char *s1, const char *s2, int count); -int V_strcasecmp (const char *s1, const char *s2); -int V_strncasecmp (const char *s1, const char *s2, int n); -int V_strnicmp (const char *s1, const char *s2, int n); -int V_atoi (const char *str); -int64 V_atoi64(const char *str); -uint64 V_atoui64(const char *str); -float V_atof (const char *str); -char* V_stristr( char* pStr, const char* pSearch ); -const char* V_stristr( const char* pStr, const char* pSearch ); -const char* V_strnistr( const char* pStr, const char* pSearch, int n ); -const char* V_strnchr( const char* pStr, char c, int n ); - // returns string immediately following prefix, (ie str+strlen(prefix)) or NULL if prefix not found -const char *StringAfterPrefix ( const char *str, const char *prefix ); -const char *StringAfterPrefixCaseSensitive( const char *str, const char *prefix ); -inline bool StringHasPrefix ( const char *str, const char *prefix ) { return StringAfterPrefix ( str, prefix ) != NULL; } -inline bool StringHasPrefixCaseSensitive( const char *str, const char *prefix ) { return StringAfterPrefixCaseSensitive( str, prefix ) != NULL; } +PLATFORM_INTERFACE const char *_V_StringAfterPrefix( const char *str, const char *prefix ); +PLATFORM_INTERFACE const char *_V_StringAfterPrefixCaseSensitive( const char *str, const char *prefix ); +#define V_StringAfterPrefix(str, prefix) _V_StringAfterPrefix((str), (prefix)) +#define V_StringAfterPrefixCaseSensitive(str, prefix) _V_StringAfterPrefixCaseSensitive((str), (prefix)) + +inline bool V_StringHasPrefix ( const char *str, const char *prefix ) { return V_StringAfterPrefix( str, prefix ) != NULL; } +inline bool V_StringHasPrefixCaseSensitive( const char *str, const char *prefix ) { return V_StringAfterPrefixCaseSensitive( str, prefix ) != NULL; } // Normalizes a float string in place. // (removes leading zeros, trailing zeros after the decimal point, and the decimal point itself where possible) -void V_normalizeFloatString( char* pFloat ); - -inline 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 -} - - -// These are versions of functions that guarantee NULL termination. -// -// maxLen is the maximum number of bytes in the destination string. -// pDest[maxLen-1] is always NULL terminated if pSrc's length is >= maxLen. -// -// This means the last parameter can usually be a sizeof() of a string. -void V_strncpy( char *pDest, const char *pSrc, int maxLen ); -int V_snprintf( char *pDest, int destLen, const char *pFormat, ... ) FMTFUNCTION( 3, 4 ); -void V_wcsncpy( wchar_t *pDest, wchar_t const *pSrc, int maxLenInBytes ); -int V_snwprintf( wchar_t *pDest, int destLen, const wchar_t *pFormat, ... ); - -#define COPY_ALL_CHARACTERS -1 -char *V_strncat(char *, const char *, size_t destBufferSize, int max_chars_to_copy=COPY_ALL_CHARACTERS ); -char *V_strnlwr(char *, size_t); - +PLATFORM_INTERFACE void V_normalizeFloatString( char* pFloat ); +PLATFORM_INTERFACE void V_normalizeFloatWString( wchar_t* pFloat ); // UNDONE: Find a non-compiler-specific way to do this #ifdef _WIN32 @@ -333,6 +349,55 @@ typedef char * va_list; #include #endif +// Prints out a pretified memory counter string value ( e.g., 7,233.27 Mb, 1,298.003 Kb, 127 bytes ) +PLATFORM_INTERFACE char *V_PrettifyMem( float value, int digitsafterdecimal = 2, bool usebinaryonek = false ); + +// Prints out a pretified integer with comma separators (eg, 7,233,270,000) +PLATFORM_INTERFACE char *V_PrettifyNum( int64 value ); + +// Returns the UTF8 encoded length in this byte +PLATFORM_INTERFACE int V_UTF8LenFromFirst( char c ); + +// Conversion functions, returning the number of bytes consumed +PLATFORM_INTERFACE int V_UTF8ToUChar32( const char *str, char32_t &result, bool &failed ); +PLATFORM_INTERFACE int V_UTF32ToUChar32( const char32_t *str, char32_t &result, bool &failed ); + +PLATFORM_INTERFACE int V_UChar32ToUTF16( const char32_t *str, char16_t *result ); +PLATFORM_INTERFACE int V_UChar32ToUTF8( const char32_t *str, char *result ); + +PLATFORM_INTERFACE int V_UTF8ToUTF16( const char *str, char16_t *dest, int dest_size, EStringConvertErrorPolicy policy ); +PLATFORM_INTERFACE int V_UTF8CharsToUTF16( const char *str, int size, char16_t *dest, int dest_size, EStringConvertErrorPolicy policy ); +PLATFORM_INTERFACE int V_UTF8ToUTF32( const char *str, char32_t *dest, int dest_size, EStringConvertErrorPolicy policy ); +PLATFORM_INTERFACE int V_UTF8CharsToUTF32( const char *str, int size, char32_t *dest, int dest_size, EStringConvertErrorPolicy policy ); + +PLATFORM_INTERFACE int V_UTF16ToUTF8( const char16_t *str, char *dest, int dest_size, EStringConvertErrorPolicy policy ); +PLATFORM_INTERFACE int V_UTF16CharsToUTF8( const char16_t *str, int size, char *dest, int dest_size, EStringConvertErrorPolicy policy ); +PLATFORM_INTERFACE int V_UTF16ToUTF16( const char16_t *str, char16_t *dest, int dest_size, EStringConvertErrorPolicy policy ); +PLATFORM_INTERFACE int V_UTF16ToUTF32( const char16_t *str, char32_t *dest, int dest_size, EStringConvertErrorPolicy policy ); +PLATFORM_INTERFACE int V_UTF16CharsToUTF32( const char16_t *str, int size, char32_t *dest, int dest_size, EStringConvertErrorPolicy policy ); + +PLATFORM_INTERFACE int V_UTF32ToUTF8( const char32_t *str, char *dest, int dest_size, EStringConvertErrorPolicy policy ); +PLATFORM_INTERFACE int V_UTF32CharsToUTF8( const char32_t *str, int size, char *dest, int dest_size, EStringConvertErrorPolicy policy ); +PLATFORM_INTERFACE int V_UTF32ToUTF16( const char32_t *str, char16_t *dest, int dest_size, EStringConvertErrorPolicy policy ); +PLATFORM_INTERFACE int V_UTF32CharsToUTF16( const char32_t *str, int size, char16_t *dest, int dest_size, EStringConvertErrorPolicy policy ); +PLATFORM_INTERFACE int V_UTF32ToUTF32( const char32_t *str, char32_t *dest, int dest_size, EStringConvertErrorPolicy policy ); + +// Functions for converting hexidecimal character strings back into binary data etc. +// +// e.g., +// int output; +// V_hextobinary( "ffffffff", 8, &output, sizeof( output ) ); +// would make output == 0xfffffff or -1 +// Similarly, +// char buffer[ 9 ]; +// V_binarytohex( &output, sizeof( output ), buffer, sizeof( buffer ) ); +// would put "ffffffff" into buffer (note null terminator!!!) +PLATFORM_INTERFACE void _V_hextobinary( char const *in, int numchars, byte *out, int maxoutputbytes ); +PLATFORM_INTERFACE void _V_binarytohex( const byte *in, int inputbytes, char *out, int outsize ); + +#define V_HexToBinary(in, numchars, out, maxoutputbytes) _V_hextobinary((in), (numchars), (out), (maxoutputbytes)) +#define V_BinaryToHex(in, inputbytes, out, outsize) _V_binarytohex((in), (inputbytes), (out), (outsize)) + #ifdef _WIN32 #define CORRECT_PATH_SEPARATOR '\\' #define CORRECT_PATH_SEPARATOR_S "\\" @@ -345,174 +410,135 @@ typedef char * va_list; #define INCORRECT_PATH_SEPARATOR_S "\\" #endif -int V_vsnprintf( char *pDest, int maxLenInCharacters, const char *pFormat, va_list params ); -template int V_vsprintf_safe( char (&pDest)[maxLenInCharacters], const char *pFormat, va_list params ) { return V_vsnprintf( pDest, maxLenInCharacters, pFormat, params ); } -int V_vsnprintf( char *pDest, int maxLen, const char *pFormat, va_list params ); - -// Prints out a pretified memory counter string value ( e.g., 7,233.27 Mb, 1,298.003 Kb, 127 bytes ) -char *V_pretifymem( float value, int digitsafterdecimal = 2, bool usebinaryonek = false ); - -// Prints out a pretified integer with comma separators (eg, 7,233,270,000) -char *V_pretifynum( int64 value ); - -// conversion functions wchar_t <-> char, returning the number of characters converted -int V_UTF8ToUnicode( const char *pUTF8, wchar_t *pwchDest, int cubDestSizeInBytes ); -int V_UnicodeToUTF8( const wchar_t *pUnicode, char *pUTF8, int cubDestSizeInBytes ); -int V_UCS2ToUnicode( const ucs2 *pUCS2, wchar_t *pUnicode, int cubDestSizeInBytes ); -int V_UCS2ToUTF8( const ucs2 *pUCS2, char *pUTF8, int cubDestSizeInBytes ); - -// Functions for converting hexidecimal character strings back into binary data etc. -// -// e.g., -// int output; -// V_hextobinary( "ffffffff", 8, &output, sizeof( output ) ); -// would make output == 0xfffffff or -1 -// Similarly, -// char buffer[ 9 ]; -// V_binarytohex( &output, sizeof( output ), buffer, sizeof( buffer ) ); -// would put "ffffffff" into buffer (note null terminator!!!) -void V_hextobinary( char const *in, int numchars, byte *out, int maxoutputbytes ); -void V_binarytohex( const byte *in, int inputbytes, char *out, int outsize ); - // Tools for working with filenames // Extracts the base name of a file (no path, no extension, assumes '/' or '\' as path separator) -void V_FileBase( const char *in, char *out,int maxlen ); +PLATFORM_INTERFACE void _V_FileBase( const char *in, char *out, int maxlen ); +#define V_FileBase _V_FileBase + // Remove the final characters of ppath if it's '\' or '/'. -void V_StripTrailingSlash( char *ppath ); +PLATFORM_INTERFACE void V_StripTrailingSlash( char *ppath ); + // Remove any extension from in and return resulting string in out -void V_StripExtension( const char *in, char *out, int outLen ); +PLATFORM_INTERFACE void _V_StripExtension( const char *in, char *out, int outLen ); +#define V_StripExtension _V_StripExtension + // Make path end with extension if it doesn't already have an extension -void V_DefaultExtension( char *path, const char *extension, int pathStringLength ); +PLATFORM_INTERFACE void _V_DefaultExtension( char *path, const char *extension, int pathStringLength ); +#define V_DefaultExtension _V_DefaultExtension + // Strips any current extension from path and ensures that extension is the new extension. // NOTE: extension string MUST include the . character -void V_SetExtension( char *path, const char *extension, int pathStringLength ); +PLATFORM_INTERFACE void _V_SetExtension( char *path, const char *extension, int pathStringLength ); +#define V_SetExtension _V_SetExtension + // Removes any filename from path ( strips back to previous / or \ character ) -void V_StripFilename( char *path ); +PLATFORM_INTERFACE void V_StripFilename( char *path ); + // Remove the final directory from the path -bool V_StripLastDir( char *dirName, int maxlen ); +PLATFORM_INTERFACE bool _V_StripLastDir( char *dirName, int maxlen ); +#define V_StripLastDir _V_StripLastDir + // Returns a pointer to the unqualified file name (no path) of a file name -const char * V_UnqualifiedFileName( const char * in ); +PLATFORM_INTERFACE const char *V_UnqualifiedFileName( const char *in ); + // Given a path and a filename, composes "path\filename", inserting the (OS correct) separator if necessary -void V_ComposeFileName( const char *path, const char *filename, char *dest, int destSize ); +PLATFORM_INTERFACE void _V_ComposeFileName( const char *path, const char *filename, char *dest, int destSize ); +#define V_ComposeFileName _V_ComposeFileName // Copy out the path except for the stuff after the final pathseparator -bool V_ExtractFilePath( const char *path, char *dest, int destSize ); -// Copy out the file extension into dest -void V_ExtractFileExtension( const char *path, char *dest, int destSize ); +PLATFORM_INTERFACE bool _V_ExtractFilePath( const char *path, char *dest, int destSize ); +#define V_ExtractFilePath _V_ExtractFilePath -const char *V_GetFileExtension( const char * path ); +// Copy out the file extension into dest +PLATFORM_INTERFACE void _V_ExtractFileExtension( const char *path, char *dest, int destSize ); +#define V_ExtractFileExtension _V_ExtractFileExtension + +PLATFORM_INTERFACE const char *V_GetFileExtension( const char *path ); +// Returns empty string instead of null on failure +PLATFORM_INTERFACE const char *V_GetFileExtensionSafe( const char *path ); // This removes "./" and "../" from the pathname. pFilename should be a full pathname. // Returns false if it tries to ".." past the root directory in the drive (in which case // it is an invalid path). -bool V_RemoveDotSlashes( char *pFilename, char separator = CORRECT_PATH_SEPARATOR ); +PLATFORM_INTERFACE bool V_RemoveDotSlashes( char *pFilename, char separator = CORRECT_PATH_SEPARATOR ); // If pPath is a relative path, this function makes it into an absolute path // using the current working directory as the base, or pStartingDir if it's non-NULL. // Returns false if it runs out of room in the string, or if pPath tries to ".." past the root directory. -void V_MakeAbsolutePath( char *pOut, int outLen, const char *pPath, const char *pStartingDir = NULL ); +PLATFORM_INTERFACE void _V_MakeAbsolutePath( char *pOut, int outLen, const char *pPath, int, const char *pStartingDir = NULL ); +#define V_MakeAbsolutePath _V_MakeAbsolutePath // Creates a relative path given two full paths // The first is the full path of the file to make a relative path for. // The second is the full path of the directory to make the first file relative to // Returns false if they can't be made relative (on separate drives, for example) -bool V_MakeRelativePath( const char *pFullPath, const char *pDirectory, char *pRelativePath, int nBufLen ); +PLATFORM_INTERFACE bool _V_MakeRelativePath( const char *pFullPath, const char *pDirectory, char *pRelativePath, int nBufLen, bool ); +#define V_MakeRelativePath _V_MakeRelativePath // Fixes up a file name, removing dot slashes, fixing slashes, converting to lowercase, etc. -void V_FixupPathName( char *pOut, size_t nOutLen, const char *pPath ); +PLATFORM_INTERFACE void _V_FixupPathName( char *pOut, size_t nOutLen, const char *pPath, bool convert_to_lower = true ); +#define V_FixupPathName _V_FixupPathName // Adds a path separator to the end of the string if there isn't one already. Returns false if it would run out of space. -void V_AppendSlash( char *pStr, int strSize ); +PLATFORM_INTERFACE void _V_AppendSlash( char *pStr, int strSize, char separator = CORRECT_PATH_SEPARATOR ); +#define V_AppendSlash _V_AppendSlash // Returns true if the path is an absolute path. -bool V_IsAbsolutePath( const char *pPath ); +PLATFORM_INTERFACE bool V_IsAbsolutePath( const char *pPath ); // Scans pIn and replaces all occurences of pMatch with pReplaceWith. // Writes the result to pOut. // Returns true if it completed successfully. // If it would overflow pOut, it fills as much as it can and returns false. -bool V_StrSubst( const char *pIn, const char *pMatch, const char *pReplaceWith, - char *pOut, int outLen, bool bCaseSensitive=false ); +PLATFORM_INTERFACE bool _V_StrSubst( const char *pIn, const char *pMatch, const char *pReplaceWith, + char *pOut, int outLen, bool bCaseSensitive=false ); +#define V_StrSubst _V_StrSubst - -// If possible, use CSplitString instead -// AM TODO: These are exported by tier0, but will require changes to CUtlVector -// Split the specified string on the specified separator. +// AM TODO: If possible, use CSplitString instead rn. +// These are exported by tier0, but will require changes to CUtlVector (additional template arg) +// +// Split the specified string on the specified separator. // Returns a list of strings separated by pSeparator. // You are responsible for freeing the contents of outStrings (call outStrings.PurgeAndDeleteElements). -void V_SplitString( const char *pString, const char *pSeparator, CUtlVector > &outStrings ); +PLATFORM_OVERLOAD void V_SplitString( const char *pString, const char *pSeparator, CUtlVector> &outStrings, bool ); // Just like V_SplitString, but it can use multiple possible separators. -void V_SplitString2( const char *pString, const char **pSeparators, int nSeparators, CUtlVector > &outStrings ); - -// Returns false if the buffer is not large enough to hold the working directory name. -bool V_GetCurrentDirectory( char *pOut, int maxLen ); - -// Set the working directory thus. -bool V_SetCurrentDirectory( const char *pDirName ); - +PLATFORM_OVERLOAD void V_SplitStringInPlace( char *pString, const char *pSeparator, CUtlVector> &outStrings ); // This function takes a slice out of pStr and stores it in pOut. // It follows the Python slice convention: // Negative numbers wrap around the string (-1 references the last character). // Large numbers are clamped to the end of the string. -void V_StrSlice( const char *pStr, int firstChar, int lastCharNonInclusive, char *pOut, int outSize ); +PLATFORM_INTERFACE void _V_StrSlice( const char *pStr, int firstChar, int lastCharNonInclusive, char *pOut, int outSize ); +#define V_StrSlice _V_StrSlice // Chop off the left nChars of a string. -void V_StrLeft( const char *pStr, int nChars, char *pOut, int outSize ); +PLATFORM_INTERFACE void _V_StrLeft( const char *pStr, int nChars, char *pOut, int outSize ); +#define V_StrLeft _V_StrLeft // Chop off the right nChars of a string. -void V_StrRight( const char *pStr, int nChars, char *pOut, int outSize ); +PLATFORM_INTERFACE void _V_StrRight( const char *pStr, int nChars, char *pOut, int outSize ); +#define V_StrRight _V_StrRight // change "special" characters to have their c-style backslash sequence. like \n, \r, \t, ", etc. // returns a pointer to a newly allocated string, which you must delete[] when finished with. -char *V_AddBackSlashesToSpecialChars( char const *pSrc ); +PLATFORM_INTERFACE char *V_AddBackSlashesToSpecialChars( char const *pSrc ); // Force slashes of either type to be = separator character -void V_FixSlashes( char *pname, char separator = CORRECT_PATH_SEPARATOR ); +PLATFORM_INTERFACE void V_FixSlashes( char *pname, char separator = CORRECT_PATH_SEPARATOR ); // This function fixes cases of filenames like materials\\blah.vmt or somepath\otherpath\\ and removes the extra double slash. -void V_FixDoubleSlashes( char *pStr ); - -// Convert multibyte to wchar + back -// Specify -1 for nInSize for null-terminated string -void V_strtowcs( const char *pString, int nInSize, wchar_t *pWString, int nOutSize ); -void V_wcstostr( const wchar_t *pWString, int nInSize, char *pString, int nOutSize ); - -// buffer-safe strcat -inline void V_strcat( char *dest, const char *src, int cchDest ) -{ - V_strncat( dest, src, cchDest, COPY_ALL_CHARACTERS ); -} - -// Convert from a string to an array of integers. -void V_StringToIntArray( int *pVector, int count, const char *pString ); - -// Convert from a string to a 4 byte color value. -void V_StringToColor32( color32 *color, const char *pString ); +PLATFORM_INTERFACE void V_FixDoubleSlashes( char *pStr ); // Convert \r\n (Windows linefeeds) to \n (Unix linefeeds). -void V_TranslateLineFeedsToUnix( char *pStr ); +PLATFORM_INTERFACE void V_TranslateLineFeedsToUnix( char *pStr ); //----------------------------------------------------------------------------- // generic unique name helper functions //----------------------------------------------------------------------------- // returns -1 if no match, nDefault if pName==prefix, and N if pName==prefix+N -inline int V_IndexAfterPrefix( const char *pName, const char *prefix, int nDefault = 0 ) -{ - if ( !pName || !prefix ) - return -1; - - const char *pIndexStr = StringAfterPrefix( pName, prefix ); - if ( !pIndexStr ) - return -1; - - if ( !*pIndexStr ) - return nDefault; - - return atoi( pIndexStr ); -} +PLATFORM_INTERFACE int V_IndexAfterPrefix( const char *pName, const char *prefix, int nDefault = 0 ); // returns startindex if none found, 2 if "prefix" found, and n+1 if "prefixn" found template < class NameArray > @@ -574,43 +600,14 @@ bool V_GenerateUniqueName( char *name, int memsize, const char *prefix, const Na return true; } - -extern bool V_StringToBin( const char*pString, void *pBin, uint nBinSize ); -extern bool V_BinToString( char*pString, void *pBin, uint nBinSize ); - -template -struct BinString_t -{ - BinString_t(){} - BinString_t( const char *pStr ) - { - V_strncpy( m_string, pStr, sizeof(m_string) ); - ToBin(); - } - BinString_t( const T & that ) - { - m_bin = that; - ToString(); - } - bool ToBin() - { - return V_StringToBin( m_string, &m_bin, sizeof( m_bin ) ); - } - void ToString() - { - V_BinToString( m_string, &m_bin, sizeof( m_bin ) ); - } - T m_bin; - char m_string[sizeof(T)*2+2]; // 0-terminated string representing the binary data in hex -}; - -template -inline BinString_t MakeBinString( const T& that ) -{ - return BinString_t( that ); -} - - +// 3d memcpy. Copy (up-to) 3 dimensional data with arbitrary source and destination +// strides. Optimizes to just a single memcpy when possible. For 2d data, set numslices to 1. +PLATFORM_INTERFACE void V_CopyMemory3D( + void *pDestAdr, void const *pSrcAdr, + int nNumCols, int nNumRows, int nNumSlices, // dimensions of copy + int nSrcBytesPerRow, int nSrcBytesPerSlice, // strides for source. + int nDestBytesPerRow, int nDestBytesPerSlice // strides for dest +); // NOTE: This is for backward compatability! // We need to DLL-export the Q methods in vstdlib but not link to them in other projects @@ -627,12 +624,12 @@ inline BinString_t MakeBinString( const T& that ) #define Q_wcscmp V_wcscmp #define Q_stricmp V_stricmp #define Q_strstr V_strstr -#define Q_strupr V_strupr +#define Q_strupr V_strupper #define Q_strlower V_strlower #define Q_wcslen V_wcslen #define Q_strncmp V_strncmp -#define Q_strcasecmp V_strcasecmp -#define Q_strncasecmp V_strncasecmp +#define Q_strcasecmp V_stricmp +#define Q_strncasecmp V_strnicmp #define Q_strnicmp V_strnicmp #define Q_atoi V_atoi #define Q_atoi64 V_atoi64 @@ -645,17 +642,14 @@ inline BinString_t MakeBinString( const T& that ) #define Q_strncpy V_strncpy #define Q_wcsncpy V_wcsncpy #define Q_snprintf V_snprintf -#define Q_snwprintf V_snwprintf +#define Q_snwprintf V_snwprintf_bytes #define Q_wcsncpy V_wcsncpy #define Q_strncat V_strncat -#define Q_strnlwr V_strnlwr #define Q_vsnprintf V_vsnprintf -#define Q_pretifymem V_pretifymem -#define Q_pretifynum V_pretifynum -#define Q_UTF8ToUnicode V_UTF8ToUnicode -#define Q_UnicodeToUTF8 V_UnicodeToUTF8 -#define Q_hextobinary V_hextobinary -#define Q_binarytohex V_binarytohex +#define Q_pretifymem V_PrettifyMem +#define Q_pretifynum V_PrettifyNum +#define Q_hextobinary V_HexToBinary +#define Q_binarytohex V_BinaryToHex #define Q_FileBase V_FileBase #define Q_StripTrailingSlash V_StripTrailingSlash #define Q_StripExtension V_StripExtension @@ -674,18 +668,14 @@ inline BinString_t MakeBinString( const T& that ) #define Q_IsAbsolutePath V_IsAbsolutePath #define Q_StrSubst V_StrSubst #define Q_SplitString V_SplitString -#define Q_SplitString2 V_SplitString2 #define Q_StrSlice V_StrSlice #define Q_StrLeft V_StrLeft #define Q_StrRight V_StrRight #define Q_FixSlashes V_FixSlashes -#define Q_strtowcs V_strtowcs -#define Q_wcstostr V_wcstostr #define Q_strcat V_strcat #define Q_MakeRelativePath V_MakeRelativePath #define Q_FixupPathName V_FixupPathName #endif // !defined( VSTDLIB_DLL_EXPORT ) - #endif // TIER1_STRTOOLS_H diff --git a/tier1/commandbuffer.cpp b/tier1/commandbuffer.cpp index a8f600a7..f3da734b 100644 --- a/tier1/commandbuffer.cpp +++ b/tier1/commandbuffer.cpp @@ -1,4 +1,4 @@ -//===== Copyright © 1996-2006, Valve Corporation, All rights reserved. ======// +//===== Copyright � 1996-2006, Valve Corporation, All rights reserved. ======// // // Purpose: // diff --git a/tier1/strtools.cpp b/tier1/strtools.cpp deleted file mode 100644 index cdb7ac07..00000000 --- a/tier1/strtools.cpp +++ /dev/null @@ -1,2017 +0,0 @@ -//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======// -// -// Purpose: String Tools -// -//===========================================================================// - -// These are redefined in the project settings to prevent anyone from using them. -// We in this module are of a higher caste and thus are privileged in their use. -#ifdef strncpy - #undef strncpy -#endif - -#ifdef _snprintf - #undef _snprintf -#endif - -#if defined( sprintf ) - #undef sprintf -#endif - -#if defined( vsprintf ) - #undef vsprintf -#endif - -#ifdef _vsnprintf -#ifdef _WIN32 - #undef _vsnprintf -#endif -#endif - -#ifdef vsnprintf -#ifndef _WIN32 - #undef vsnprintf -#endif -#endif - -#if defined( strcat ) - #undef strcat -#endif - -#ifdef strncat - #undef strncat -#endif - -// NOTE: I have to include stdio + stdarg first so vsnprintf gets compiled in -#include -#include - -#if defined _LINUX || defined __APPLE__ -#include -#include -#include -#define _getcwd getcwd -#elif _WIN32 -#include -#if !defined( _X360 ) -#define WIN32_LEAN_AND_MEAN -#include -#endif -#endif - -#ifdef _WIN32 -#ifndef CP_UTF8 -#define CP_UTF8 65001 -#endif -#endif -#include "tier0/dbg.h" -#include "tier1/strtools.h" -#include -#include -#include "tier0/basetypes.h" -#include "tier1/utldict.h" -#if defined( _X360 ) -#include "xbox/xbox_win32stubs.h" -#endif -#include "tier0/memdbgon.h" - -void _V_memset (void *dest, int fill, int count) -{ - Assert( count >= 0 ); - AssertValidWritePtr( dest, count ); - - memset(dest,fill,count); -} - -void _V_memcpy (void *dest, const void *src, int count) -{ - Assert( count >= 0 ); - AssertValidReadPtr( src, count ); - AssertValidWritePtr( dest, count ); - - memcpy( dest, src, count ); -} - -void _V_memmove(void *dest, const void *src, int count) -{ - Assert( count >= 0 ); - AssertValidReadPtr( src, count ); - AssertValidWritePtr( dest, count ); - - memmove( dest, src, count ); -} - -int _V_memcmp (const void *m1, const void *m2, int count) -{ - Assert( count >= 0 ); - AssertValidReadPtr( m1, count ); - AssertValidReadPtr( m2, count ); - - return memcmp( m1, m2, count ); -} - -int _V_strlen(const char *str) -{ - AssertValidStringPtr(str); - return strlen( str ); -} - -void _V_strcpy (char *dest, const char *src) -{ - AssertValidWritePtr(dest); - AssertValidStringPtr(src); - - strcpy( dest, src ); -} - -int _V_wcslen(const wchar_t *pwch) -{ - return wcslen( pwch ); -} - -char *_V_strrchr(const char *s, char c) -{ - AssertValidStringPtr( s ); - int len = V_strlen(s); - s += len; - while (len--) - if (*--s == c) return (char *)s; - return 0; -} - -int _V_strcmp (const char *s1, const char *s2) -{ - AssertValidStringPtr( s1 ); - AssertValidStringPtr( s2 ); - - return strcmp( s1, s2 ); -} - -int _V_wcscmp (const wchar_t *s1, const wchar_t *s2) -{ - while (1) - { - if (*s1 != *s2) - return -1; // strings not equal - if (!*s1) - return 0; // strings are equal - s1++; - s2++; - } - - return -1; -} - -#ifdef PLATFORM_WINDOWS -#undef stricmp -#endif - -int _V_stricmp( const char *s1, const char *s2 ) -{ - AssertValidStringPtr( s1 ); - AssertValidStringPtr( s2 ); - - return stricmp( s1, s2 ); -} - - -char *_V_strstr( const char *s1, const char *search ) -{ - AssertValidStringPtr( s1 ); - AssertValidStringPtr( search ); - -#if defined( _X360 ) - return (char *)strstr( (char *)s1, search ); -#else - return (char *)strstr( s1, search ); -#endif -} - -char *_V_strupr (char *start) -{ - AssertValidStringPtr( start ); - return strupr( start ); -} - - -char *_V_strlower (char *start) -{ - AssertValidStringPtr( start ); - return strlwr(start); -} - -int V_strncmp (const char *s1, const char *s2, int count) -{ - Assert( count >= 0 ); - AssertValidStringPtr( s1, count ); - AssertValidStringPtr( s2, count ); - - while ( count-- > 0 ) - { - if ( *s1 != *s2 ) - return *s1 < *s2 ? -1 : 1; // string different - if ( *s1 == '\0' ) - return 0; // null terminator hit - strings the same - s1++; - s2++; - } - - return 0; // count characters compared the same -} - -char *V_strnlwr(char *s, size_t count) -{ - Assert( count >= 0 ); - AssertValidStringPtr( s, count ); - - char* pRet = s; - if ( !s ) - return s; - - while ( count-- ) - { - if ( !*s ) - break; - - *s = tolower( *s ); - ++s; - } - - if ( count > 0 ) - { - s[count-1] = 0; - } - - return pRet; -} - - -int V_strncasecmp (const char *s1, const char *s2, int n) -{ - Assert( n >= 0 ); - AssertValidStringPtr( s1 ); - AssertValidStringPtr( s2 ); - - while ( n-- > 0 ) - { - int c1 = *s1++; - int c2 = *s2++; - - if (c1 != c2) - { - if (c1 >= 'a' && c1 <= 'z') - c1 -= ('a' - 'A'); - if (c2 >= 'a' && c2 <= 'z') - c2 -= ('a' - 'A'); - if (c1 != c2) - return c1 < c2 ? -1 : 1; - } - if ( c1 == '\0' ) - return 0; // null terminator hit - strings the same - } - - return 0; // n characters compared the same -} - -int V_strcasecmp( const char *s1, const char *s2 ) -{ - AssertValidStringPtr( s1 ); - AssertValidStringPtr( s2 ); - - return stricmp( s1, s2 ); -} - -int V_strnicmp (const char *s1, const char *s2, int n) -{ - Assert( n >= 0 ); - AssertValidStringPtr(s1); - AssertValidStringPtr(s2); - - return V_strncasecmp( s1, s2, n ); -} - - -const char *StringAfterPrefix( const char *str, const char *prefix ) -{ - AssertValidStringPtr( str ); - AssertValidStringPtr( prefix ); - do - { - if ( !*prefix ) - return str; - } - while ( tolower( *str++ ) == tolower( *prefix++ ) ); - return NULL; -} - -const char *StringAfterPrefixCaseSensitive( const char *str, const char *prefix ) -{ - AssertValidStringPtr( str ); - AssertValidStringPtr( prefix ); - do - { - if ( !*prefix ) - return str; - } - while ( *str++ == *prefix++ ); - return NULL; -} - - -int V_atoi (const char *str) -{ - AssertValidStringPtr( str ); - - int val; - int sign; - int c; - - Assert( str ); - if (*str == '-') - { - sign = -1; - str++; - } - else - sign = 1; - - val = 0; - -// -// check for hex -// - if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X') ) - { - str += 2; - while (1) - { - c = *str++; - if (c >= '0' && c <= '9') - val = (val<<4) + c - '0'; - else if (c >= 'a' && c <= 'f') - val = (val<<4) + c - 'a' + 10; - else if (c >= 'A' && c <= 'F') - val = (val<<4) + c - 'A' + 10; - else - return val*sign; - } - } - -// -// check for character -// - if (str[0] == '\'') - { - return sign * str[1]; - } - -// -// assume decimal -// - while (1) - { - c = *str++; - if (c <'0' || c > '9') - return val*sign; - val = val*10 + c - '0'; - } - - return 0; -} - - -float V_atof (const char *str) -{ - AssertValidStringPtr( str ); - double val; - int sign; - int c; - int decimal, total; - - if (*str == '-') - { - sign = -1; - str++; - } - else - sign = 1; - - val = 0; - -// -// check for hex -// - if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X') ) - { - str += 2; - while (1) - { - c = *str++; - if (c >= '0' && c <= '9') - val = (val*16) + c - '0'; - else if (c >= 'a' && c <= 'f') - val = (val*16) + c - 'a' + 10; - else if (c >= 'A' && c <= 'F') - val = (val*16) + c - 'A' + 10; - else - return val*sign; - } - } - -// -// check for character -// - if (str[0] == '\'') - { - return sign * str[1]; - } - -// -// assume decimal -// - decimal = -1; - total = 0; - while (1) - { - c = *str++; - if (c == '.') - { - decimal = total; - continue; - } - if (c <'0' || c > '9') - break; - val = val*10 + c - '0'; - total++; - } - - if (decimal == -1) - return val*sign; - while (total > decimal) - { - val /= 10; - total--; - } - - return val*sign; -} - -//----------------------------------------------------------------------------- -// Normalizes a float string in place. -// -// (removes leading zeros, trailing zeros after the decimal point, and the decimal point itself where possible) -//----------------------------------------------------------------------------- -void V_normalizeFloatString( char* pFloat ) -{ - // If we have a decimal point, remove trailing zeroes: - if( strchr( pFloat,'.' ) ) - { - int len = V_strlen(pFloat); - - while( len > 1 && pFloat[len - 1] == '0' ) - { - pFloat[len - 1] = '\0'; - len--; - } - - if( len > 1 && pFloat[ len - 1 ] == '.' ) - { - pFloat[len - 1] = '\0'; - len--; - } - } - - // TODO: Strip leading zeros - -} - - -//----------------------------------------------------------------------------- -// Finds a string in another string with a case insensitive test -//----------------------------------------------------------------------------- -char const* V_stristr( char const* pStr, char const* pSearch ) -{ - AssertValidStringPtr(pStr); - AssertValidStringPtr(pSearch); - - if (!pStr || !pSearch) - return 0; - - char const* pLetter = pStr; - - // Check the entire string - while (*pLetter != 0) - { - // Skip over non-matches - if (tolower((unsigned char)*pLetter) == tolower((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((unsigned char)*pMatch) != tolower((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( pStr ); - AssertValidStringPtr( pSearch ); - - return (char*)V_stristr( (char const*)pStr, pSearch ); -} - -//----------------------------------------------------------------------------- -// Finds a string in another string with a case insensitive test w/ length validation -//----------------------------------------------------------------------------- -char const* V_strnistr( char const* pStr, char const* pSearch, int n ) -{ - AssertValidStringPtr(pStr); - AssertValidStringPtr(pSearch); - - if (!pStr || !pSearch) - return 0; - - char const* pLetter = pStr; - - // Check the entire string - while (*pLetter != 0) - { - if ( n <= 0 ) - return 0; - - // Skip over non-matches - if (tolower(*pLetter) == tolower(*pSearch)) - { - int n1 = n - 1; - - // Check for match - char const* pMatch = pLetter + 1; - char const* 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 (tolower(*pMatch) != tolower(*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, int n ) -{ - char const* pLetter = pStr; - char const* pLast = pStr + n; - - // Check the entire string - while ( (pLetter < pLast) && (*pLetter != 0) ) - { - if (*pLetter == c) - return pLetter; - ++pLetter; - } - return NULL; -} - -void V_strncpy( char *pDest, char const *pSrc, int maxLen ) -{ - Assert( maxLen >= 0 ); - AssertValidWritePtr( pDest, maxLen ); - AssertValidStringPtr( pSrc ); - - strncpy( pDest, pSrc, maxLen ); - if ( maxLen > 0 ) - { - pDest[maxLen-1] = 0; - } -} - -void V_wcsncpy( wchar_t *pDest, wchar_t const *pSrc, int maxLenInBytes ) -{ - Assert( maxLenInBytes >= 0 ); - AssertValidWritePtr( pDest, maxLenInBytes ); - AssertValidReadPtr( pSrc ); - - int maxLen = maxLenInBytes / sizeof(wchar_t); - - wcsncpy( pDest, pSrc, maxLen ); - if( maxLen ) - { - pDest[maxLen-1] = 0; - } -} - - - -int V_snwprintf( wchar_t *pDest, int maxLen, const wchar_t *pFormat, ... ) -{ - Assert( maxLen >= 0 ); - AssertValidWritePtr( pDest, maxLen ); - AssertValidReadPtr( pFormat ); - - va_list marker; - - va_start( marker, pFormat ); -#ifdef _WIN32 - int len = _snwprintf( pDest, maxLen, pFormat, marker ); -#elif defined _LINUX || defined __APPLE__ - int len = swprintf( pDest, maxLen, pFormat, marker ); -#else -#error "define vsnwprintf type." -#endif - va_end( marker ); - - // Len < 0 represents an overflow - if( len < 0 ) - { - len = maxLen; - pDest[maxLen-1] = 0; - } - - return len; -} - - -int V_snprintf( char *pDest, int maxLen, char const *pFormat, ... ) -{ - Assert( maxLen >= 0 ); - AssertValidWritePtr( pDest, maxLen ); - AssertValidStringPtr( pFormat ); - - va_list marker; - - va_start( marker, pFormat ); -#ifdef _WIN32 - int len = _vsnprintf( pDest, maxLen, pFormat, marker ); -#elif defined _LINUX || defined __APPLE__ - int len = vsnprintf( pDest, maxLen, pFormat, marker ); -#else - #error "define vsnprintf type." -#endif - va_end( marker ); - - // Len < 0 represents an overflow - if( len < 0 ) - { - len = maxLen; - pDest[maxLen-1] = 0; - } - - return len; -} - - -int V_vsnprintf( char *pDest, int maxLen, char const *pFormat, va_list params ) -{ - Assert( maxLen > 0 ); - AssertValidWritePtr( pDest, maxLen ); - AssertValidStringPtr( pFormat ); - - int len = _vsnprintf( pDest, maxLen, pFormat, params ); - - if( len < 0 ) - { - len = maxLen; - pDest[maxLen-1] = 0; - } - - return len; -} - - - -//----------------------------------------------------------------------------- -// Purpose: If COPY_ALL_CHARACTERS == max_chars_to_copy then we try to add the whole pSrc to the end of pDest, otherwise -// we copy only as many characters as are specified in max_chars_to_copy (or the # of characters in pSrc if thats's less). -// Input : *pDest - destination buffer -// *pSrc - string to append -// destBufferSize - sizeof the buffer pointed to by pDest -// max_chars_to_copy - COPY_ALL_CHARACTERS in pSrc or max # to copy -// Output : char * the copied buffer -//----------------------------------------------------------------------------- -char *V_strncat(char *pDest, const char *pSrc, size_t destBufferSize, int max_chars_to_copy ) -{ - size_t charstocopy = (size_t)0; - - Assert( destBufferSize >= 0 ); - AssertValidStringPtr( pDest); - AssertValidStringPtr( pSrc ); - - size_t len = strlen(pDest); - size_t srclen = strlen( pSrc ); - if ( max_chars_to_copy <= COPY_ALL_CHARACTERS ) - { - charstocopy = srclen; - } - else - { - charstocopy = (size_t)MIN( max_chars_to_copy, (int)srclen ); - } - - if ( len + charstocopy >= destBufferSize ) - { - charstocopy = destBufferSize - len - 1; - } - - if ( !charstocopy ) - { - return pDest; - } - - char *pOut = strncat( pDest, pSrc, charstocopy ); - pOut[destBufferSize-1] = 0; - return pOut; -} - - - -//----------------------------------------------------------------------------- -// Purpose: Converts value into x.xx MB/ x.xx KB, x.xx bytes format, including commas -// Input : value - -// 2 - -// false - -// Output : char -//----------------------------------------------------------------------------- -#define NUM_PRETIFYMEM_BUFFERS 8 -char *V_pretifymem( float value, int digitsafterdecimal /*= 2*/, bool usebinaryonek /*= false*/ ) -{ - static char output[ NUM_PRETIFYMEM_BUFFERS ][ 32 ]; - static int current; - - float onekb = usebinaryonek ? 1024.0f : 1000.0f; - float onemb = onekb * onekb; - - char *out = output[ current ]; - current = ( current + 1 ) & ( NUM_PRETIFYMEM_BUFFERS -1 ); - - char suffix[ 8 ]; - - // First figure out which bin to use - if ( value > onemb ) - { - value /= onemb; - V_snprintf( suffix, sizeof( suffix ), " MB" ); - } - else if ( value > onekb ) - { - value /= onekb; - V_snprintf( suffix, sizeof( suffix ), " KB" ); - } - else - { - V_snprintf( suffix, sizeof( suffix ), " bytes" ); - } - - char val[ 32 ]; - - // Clamp to >= 0 - digitsafterdecimal = MAX( digitsafterdecimal, 0 ); - - // If it's basically integral, don't do any decimals - if ( FloatMakePositive( value - (int)value ) < 0.00001 ) - { - V_snprintf( val, sizeof( val ), "%i%s", (int)value, suffix ); - } - else - { - char fmt[ 32 ]; - - // Otherwise, create a format string for the decimals - V_snprintf( fmt, sizeof( fmt ), "%%.%if%s", digitsafterdecimal, suffix ); - V_snprintf( val, sizeof( val ), fmt, value ); - } - - // Copy from in to out - char *i = val; - char *o = out; - - // Search for decimal or if it was integral, find the space after the raw number - char *dot = strstr( i, "." ); - if ( !dot ) - { - dot = strstr( i, " " ); - } - - // Compute position of dot - int pos = dot - i; - // Don't put a comma if it's <= 3 long - pos -= 3; - - while ( *i ) - { - // If pos is still valid then insert a comma every third digit, except if we would be - // putting one in the first spot - if ( pos >= 0 && !( pos % 3 ) ) - { - // Never in first spot - if ( o != out ) - { - *o++ = ','; - } - } - - // Count down comma position - pos--; - - // Copy rest of data as normal - *o++ = *i++; - } - - // Terminate - *o = 0; - - return out; -} - -//----------------------------------------------------------------------------- -// Purpose: Returns a string representation of an integer with commas -// separating the 1000s (ie, 37,426,421) -// Input : value - Value to convert -// Output : Pointer to a static buffer containing the output -//----------------------------------------------------------------------------- -#define NUM_PRETIFYNUM_BUFFERS 8 -char *V_pretifynum( int64 value ) -{ - static char output[ NUM_PRETIFYMEM_BUFFERS ][ 32 ]; - static int current; - - char *out = output[ current ]; - current = ( current + 1 ) & ( NUM_PRETIFYMEM_BUFFERS -1 ); - - *out = 0; - - // Render the leading -, if necessary - if ( value < 0 ) - { - char *pchRender = out + V_strlen( out ); - V_snprintf( pchRender, 32, "-" ); - value = -value; - } - - // Render quadrillions - if ( value >= 1000000000000LL ) - { - char *pchRender = out + V_strlen( out ); - V_snprintf( pchRender, 32, "%lld,", value / 1000000000000LL ); - } - - // Render trillions - if ( value >= 1000000000000LL ) - { - char *pchRender = out + V_strlen( out ); - V_snprintf( pchRender, 32, "%lld,", value / 1000000000000LL ); - } - - // Render billions - if ( value >= 1000000000 ) - { - char *pchRender = out + V_strlen( out ); - V_snprintf( pchRender, 32, "%lld,", value / 1000000000 ); - } - - // Render millions - if ( value >= 1000000 ) - { - char *pchRender = out + V_strlen( out ); - if ( value >= 1000000000 ) - V_snprintf( pchRender, 32, "%03d,", (unsigned int)(( value / 1000000 ) % 1000 )); - else - V_snprintf( pchRender, 32, "%d,", (unsigned int)(( value / 1000000 ) % 1000 )); - } - - // Render thousands - if ( value >= 1000 ) - { - char *pchRender = out + V_strlen( out ); - if ( value >= 1000000 ) - V_snprintf( pchRender, 32, "%03d,", (unsigned int)(( value / 1000 ) % 1000 )); - else - V_snprintf( pchRender, 32, "%d,", (unsigned int)(( value / 1000 ) % 1000 )); - } - - // Render units - char *pchRender = out + V_strlen( out ); - if ( value > 1000 ) - V_snprintf( pchRender, 32, "%03d", (unsigned int)(value % 1000) ); - else - V_snprintf( pchRender, 32, "%d", (unsigned int)(value % 1000) ); - - return out; -} - - -//----------------------------------------------------------------------------- -// Purpose: Converts a UTF8 string into a unicode string -//----------------------------------------------------------------------------- -int V_UTF8ToUnicode( const char *pUTF8, wchar_t *pwchDest, int cubDestSizeInBytes ) -{ - AssertValidStringPtr(pUTF8); - AssertValidWritePtr(pwchDest); - - pwchDest[0] = 0; -#ifdef _WIN32 - int cchResult = MultiByteToWideChar( CP_UTF8, 0, pUTF8, -1, pwchDest, cubDestSizeInBytes / sizeof(wchar_t) ); -#elif defined _LINUX || defined __APPLE__ - 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 ) -{ - AssertValidStringPtr(pUTF8, cubDestSizeInBytes); - AssertValidReadPtr(pUnicode); - - pUTF8[0] = 0; -#ifdef _WIN32 - int cchResult = WideCharToMultiByte( CP_UTF8, 0, pUnicode, -1, pUTF8, cubDestSizeInBytes, NULL, NULL ); -#elif defined _LINUX || defined __APPLE__ - int cchResult = wcstombs( pUTF8, pUnicode, cubDestSizeInBytes ); -#endif - pUTF8[cubDestSizeInBytes - 1] = 0; - return cchResult; -} - -//----------------------------------------------------------------------------- -// Purpose: Returns the 4 bit nibble for a hex character -// Input : c - -// Output : unsigned char -//----------------------------------------------------------------------------- -static unsigned char V_nibble( char c ) -{ - if ( ( c >= '0' ) && - ( c <= '9' ) ) - { - return (unsigned char)(c - '0'); - } - - if ( ( c >= 'A' ) && - ( c <= 'F' ) ) - { - return (unsigned char)(c - 'A' + 0x0a); - } - - if ( ( c >= 'a' ) && - ( c <= 'f' ) ) - { - return (unsigned char)(c - 'a' + 0x0a); - } - - return '0'; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *in - -// numchars - -// *out - -// maxoutputbytes - -//----------------------------------------------------------------------------- -void V_hextobinary( char const *in, int numchars, byte *out, int maxoutputbytes ) -{ - int len = V_strlen( in ); - numchars = MIN( len, numchars ); - // Make sure it's even - numchars = ( numchars ) & ~0x1; - - // Must be an even # of input characters (two chars per output byte) - Assert( numchars >= 2 ); - - memset( out, 0x00, maxoutputbytes ); - - byte *p; - int i; - - p = out; - for ( i = 0; - ( i < numchars ) && ( ( p - out ) < maxoutputbytes ); - i+=2, p++ ) - { - *p = ( V_nibble( in[i] ) << 4 ) | V_nibble( in[i+1] ); - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *in - -// inputbytes - -// *out - -// outsize - -//----------------------------------------------------------------------------- -void V_binarytohex( const byte *in, int inputbytes, char *out, int outsize ) -{ - Assert( outsize >= 1 ); - char doublet[10]; - int i; - - out[0]=0; - - for ( i = 0; i < inputbytes; i++ ) - { - unsigned char c = in[i]; - V_snprintf( doublet, sizeof( doublet ), "%02x", c ); - V_strncat( out, doublet, outsize, COPY_ALL_CHARACTERS ); - } -} - -#if defined( _WIN32 ) || defined( WIN32 ) -#define PATHSEPARATOR(c) ((c) == '\\' || (c) == '/') -#else //_WIN32 -#define PATHSEPARATOR(c) ((c) == '/') -#endif //_WIN32 - - -//----------------------------------------------------------------------------- -// Purpose: Extracts the base name of a file (no path, no extension, assumes '/' or '\' as path separator) -// Input : *in - -// *out - -// maxlen - -//----------------------------------------------------------------------------- -void V_FileBase( const char *in, char *out, int maxlen ) -{ - Assert( maxlen >= 1 ); - Assert( in ); - Assert( out ); - - if ( !in || !in[ 0 ] ) - { - *out = 0; - return; - } - - int len, start, end; - - len = V_strlen( in ); - - // scan backward for '.' - end = len - 1; - while ( end&& in[end] != '.' && !PATHSEPARATOR( in[end] ) ) - { - end--; - } - - if ( in[end] != '.' ) // no '.', copy to end - { - end = len-1; - } - else - { - end--; // Found ',', copy to left of '.' - } - - // Scan backward for '/' - start = len-1; - while ( start >= 0 && !PATHSEPARATOR( in[start] ) ) - { - start--; - } - - if ( start < 0 || !PATHSEPARATOR( in[start] ) ) - { - start = 0; - } - else - { - start++; - } - - // Length of new sting - len = end - start + 1; - - int maxcopy = MIN( len + 1, maxlen ); - - // Copy partial string - V_strncpy( out, &in[start], maxcopy ); -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *ppath - -//----------------------------------------------------------------------------- -void V_StripTrailingSlash( char *ppath ) -{ - Assert( ppath ); - - int len = V_strlen( ppath ); - if ( len > 0 ) - { - if ( PATHSEPARATOR( ppath[ len - 1 ] ) ) - { - ppath[ len - 1 ] = 0; - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *in - -// *out - -// outSize - -//----------------------------------------------------------------------------- -void V_StripExtension( const char *in, char *out, int outSize ) -{ - // Find the last dot. If it's followed by a dot or a slash, then it's part of a - // directory specifier like ../../somedir/./blah. - - // scan backward for '.' - int end = V_strlen( in ) - 1; - while ( end > 0 && in[end] != '.' && !PATHSEPARATOR( in[end] ) ) - { - --end; - } - - if (end > 0 && !PATHSEPARATOR( in[end] ) && end < outSize) - { - int nChars = MIN( end, outSize-1 ); - if ( out != in ) - { - memcpy( out, in, nChars ); - } - out[nChars] = 0; - } - else - { - // nothing found - if ( out != in ) - { - V_strncpy( out, in, outSize ); - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *path - -// *extension - -// pathStringLength - -//----------------------------------------------------------------------------- -void V_DefaultExtension( char *path, const char *extension, int pathStringLength ) -{ - Assert( path ); - Assert( pathStringLength >= 1 ); - Assert( extension ); - Assert( extension[0] == '.' ); - - char *src; - - // if path doesn't have a .EXT, append extension - // (extension should include the .) - src = path + V_strlen(path) - 1; - - while ( !PATHSEPARATOR( *src ) && ( src > path ) ) - { - if (*src == '.') - { - // it has an extension - return; - } - src--; - } - - // Concatenate the desired extension - V_strncat( path, extension, pathStringLength, COPY_ALL_CHARACTERS ); -} - -//----------------------------------------------------------------------------- -// Purpose: Force extension... -// Input : *path - -// *extension - -// pathStringLength - -//----------------------------------------------------------------------------- -void V_SetExtension( char *path, const char *extension, int pathStringLength ) -{ - V_StripExtension( path, path, pathStringLength ); - V_DefaultExtension( path, extension, pathStringLength ); -} - -//----------------------------------------------------------------------------- -// Purpose: Remove final filename from string -// Input : *path - -// Output : void V_StripFilename -//----------------------------------------------------------------------------- -void V_StripFilename (char *path) -{ - int length; - - length = V_strlen( path )-1; - if ( length <= 0 ) - return; - - while ( length > 0 && - !PATHSEPARATOR( path[length] ) ) - { - length--; - } - - path[ length ] = 0; -} - -#ifdef _WIN32 -#define CORRECT_PATH_SEPARATOR '\\' -#define INCORRECT_PATH_SEPARATOR '/' -#elif defined _LINUX || defined __APPLE__ -#define CORRECT_PATH_SEPARATOR '/' -#define INCORRECT_PATH_SEPARATOR '\\' -#endif - -//----------------------------------------------------------------------------- -// Purpose: Changes all '/' or '\' characters into separator -// Input : *pname - -// separator - -//----------------------------------------------------------------------------- -void V_FixSlashes( char *pname, char separator /* = CORRECT_PATH_SEPARATOR */ ) -{ - while ( *pname ) - { - if ( *pname == INCORRECT_PATH_SEPARATOR || *pname == CORRECT_PATH_SEPARATOR ) - { - *pname = separator; - } - pname++; - } -} - - -//----------------------------------------------------------------------------- -// Purpose: This function fixes cases of filenames like materials\\blah.vmt or somepath\otherpath\\ and removes the extra double slash. -//----------------------------------------------------------------------------- -void V_FixDoubleSlashes( char *pStr ) -{ - int len = V_strlen( pStr ); - - for ( int i=1; i < len-1; i++ ) - { - if ( (pStr[i] == '/' || pStr[i] == '\\') && (pStr[i+1] == '/' || pStr[i+1] == '\\') ) - { - // This means there's a double slash somewhere past the start of the filename. That - // can happen in Hammer if they use a material in the root directory. You'll get a filename - // that looks like 'materials\\blah.vmt' - V_memmove( &pStr[i], &pStr[i+1], len - i ); - --len; - } - } -} - -//----------------------------------------------------------------------------- -// Purpose: Strip off the last directory from dirName -// Input : *dirName - -// maxlen - -// Output : Returns true on success, false on failure. -//----------------------------------------------------------------------------- -bool V_StripLastDir( char *dirName, int maxlen ) -{ - if( dirName[0] == 0 || - !V_stricmp( dirName, "./" ) || - !V_stricmp( dirName, ".\\" ) ) - return false; - - int len = V_strlen( dirName ); - - Assert( len < maxlen ); - - // skip trailing slash - if ( PATHSEPARATOR( dirName[len-1] ) ) - { - len--; - } - - while ( len > 0 ) - { - if ( PATHSEPARATOR( dirName[len-1] ) ) - { - dirName[len] = 0; - V_FixSlashes( dirName, CORRECT_PATH_SEPARATOR ); - return true; - } - len--; - } - - // Allow it to return an empty string and true. This can happen if something like "tf2/" is passed in. - // The correct behavior is to strip off the last directory ("tf2") and return true. - if( len == 0 ) - { - V_snprintf( dirName, maxlen, ".%c", CORRECT_PATH_SEPARATOR ); - return true; - } - - return true; -} - - -//----------------------------------------------------------------------------- -// Purpose: Returns a pointer to the beginning of the unqualified file name -// (no path information) -// Input: in - file name (may be unqualified, relative or absolute path) -// Output: pointer to unqualified file name -//----------------------------------------------------------------------------- -const char * V_UnqualifiedFileName( const char * in ) -{ - // back up until the character after the first path separator we find, - // or the beginning of the string - const char * out = in + strlen( in ) - 1; - while ( ( out > in ) && ( !PATHSEPARATOR( *( out-1 ) ) ) ) - out--; - return out; -} - - -//----------------------------------------------------------------------------- -// Purpose: Composes a path and filename together, inserting a path separator -// if need be -// Input: path - path to use -// filename - filename to use -// dest - buffer to compose result in -// destSize - size of destination buffer -//----------------------------------------------------------------------------- -void V_ComposeFileName( const char *path, const char *filename, char *dest, int destSize ) -{ - V_strncpy( dest, path, destSize ); - V_AppendSlash( dest, destSize ); - V_strncat( dest, filename, destSize, COPY_ALL_CHARACTERS ); - V_FixSlashes( dest ); -} - - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *path - -// *dest - -// destSize - -// Output : void V_ExtractFilePath -//----------------------------------------------------------------------------- -bool V_ExtractFilePath (const char *path, char *dest, int destSize ) -{ - Assert( destSize >= 1 ); - if ( destSize < 1 ) - { - return false; - } - - // Last char - int len = V_strlen(path); - const char *src = path + (len ? len-1 : 0); - - // back up until a \ or the start - while ( src != path && !PATHSEPARATOR( *(src-1) ) ) - { - src--; - } - - int copysize = MIN( src - path, destSize - 1 ); - memcpy( dest, path, copysize ); - dest[copysize] = 0; - - return copysize != 0 ? true : false; -} - -//----------------------------------------------------------------------------- -// Purpose: -// Input : *path - -// *dest - -// destSize - -// Output : void V_ExtractFileExtension -//----------------------------------------------------------------------------- -void V_ExtractFileExtension( const char *path, char *dest, int destSize ) -{ - *dest = '\0'; - const char * extension = V_GetFileExtension( path ); - if ( NULL != extension ) - V_strncpy( dest, extension, destSize ); -} - - -//----------------------------------------------------------------------------- -// Purpose: Returns a pointer to the file extension within a file name string -// Input: in - file name -// Output: pointer to beginning of extension (after the "."), or NULL -// if there is no extension -//----------------------------------------------------------------------------- -const char * V_GetFileExtension( const char * path ) -{ - const char *src; - - src = path + strlen(path) - 1; - -// -// back up until a . or the start -// - while (src != path && *(src-1) != '.' ) - src--; - - // check to see if the '.' is part of a pathname - if (src == path || PATHSEPARATOR( *src ) ) - { - return NULL; // no extension - } - - return src; -} - -bool V_RemoveDotSlashes( char *pFilename, char separator ) -{ - // Remove '//' or '\\' - char *pIn = pFilename; - char *pOut = pFilename; - bool bPrevPathSep = false; - while ( *pIn ) - { - bool bIsPathSep = PATHSEPARATOR( *pIn ); - if ( !bIsPathSep || !bPrevPathSep ) - { - *pOut++ = *pIn; - } - bPrevPathSep = bIsPathSep; - ++pIn; - } - *pOut = 0; - - // Get rid of "./"'s - pIn = pFilename; - pOut = pFilename; - while ( *pIn ) - { - // The logic on the second line is preventing it from screwing up "../" - if ( pIn[0] == '.' && PATHSEPARATOR( pIn[1] ) && - (pIn == pFilename || pIn[-1] != '.') ) - { - pIn += 2; - } - else - { - *pOut = *pIn; - ++pIn; - ++pOut; - } - } - *pOut = 0; - - // Get rid of a trailing "/." (needless). - int len = strlen( pFilename ); - if ( len > 2 && pFilename[len-1] == '.' && PATHSEPARATOR( pFilename[len-2] ) ) - { - pFilename[len-2] = 0; - } - - // Each time we encounter a "..", back up until we've read the previous directory name, - // then get rid of it. - pIn = pFilename; - while ( *pIn ) - { - if ( pIn[0] == '.' && - pIn[1] == '.' && - (pIn == pFilename || PATHSEPARATOR(pIn[-1])) && // Preceding character must be a slash. - (pIn[2] == 0 || PATHSEPARATOR(pIn[2])) ) // Following character must be a slash or the end of the string. - { - char *pEndOfDots = pIn + 2; - char *pStart = pIn - 2; - - // Ok, now scan back for the path separator that starts the preceding directory. - while ( 1 ) - { - if ( pStart < pFilename ) - return false; - - if ( PATHSEPARATOR( *pStart ) ) - break; - - --pStart; - } - - // Now slide the string down to get rid of the previous directory and the ".." - memmove( pStart, pEndOfDots, strlen( pEndOfDots ) + 1 ); - - // Start over. - pIn = pFilename; - } - else - { - ++pIn; - } - } - - V_FixSlashes( pFilename, separator ); - return true; -} - - -void V_AppendSlash( char *pStr, int strSize ) -{ - int len = V_strlen( pStr ); - if ( len > 0 && !PATHSEPARATOR(pStr[len-1]) ) - { - //if ( len+1 >= strSize ) - //Error( "V_AppendSlash: ran out of space on %s.", pStr ); - - pStr[len] = CORRECT_PATH_SEPARATOR; - pStr[len+1] = 0; - } -} - - -void V_MakeAbsolutePath( char *pOut, int outLen, const char *pPath, const char *pStartingDir ) -{ - if ( V_IsAbsolutePath( pPath ) ) - { - // pPath is not relative.. just copy it. - V_strncpy( pOut, pPath, outLen ); - } - else - { - // Make sure the starting directory is absolute.. - if ( pStartingDir && V_IsAbsolutePath( pStartingDir ) ) - { - V_strncpy( pOut, pStartingDir, outLen ); - } - else - { - //if ( !_getcwd( pOut, outLen ) ) - //Error( "V_MakeAbsolutePath: _getcwd failed." ); - - if ( pStartingDir ) - { - V_AppendSlash( pOut, outLen ); - V_strncat( pOut, pStartingDir, outLen, COPY_ALL_CHARACTERS ); - } - } - - // Concatenate the paths. - V_AppendSlash( pOut, outLen ); - V_strncat( pOut, pPath, outLen, COPY_ALL_CHARACTERS ); - } - - //if ( !V_RemoveDotSlashes( pOut ) ) - //Error( "V_MakeAbsolutePath: tried to \"..\" past the root." ); - - V_FixSlashes( pOut ); -} - - -//----------------------------------------------------------------------------- -// Makes a relative path -//----------------------------------------------------------------------------- -bool V_MakeRelativePath( const char *pFullPath, const char *pDirectory, char *pRelativePath, int nBufLen ) -{ - pRelativePath[0] = 0; - - const char *pPath = pFullPath; - const char *pDir = pDirectory; - - // Strip out common parts of the path - const char *pLastCommonPath = NULL; - const char *pLastCommonDir = NULL; - while ( *pPath && ( tolower( *pPath ) == tolower( *pDir ) || - ( PATHSEPARATOR( *pPath ) && ( PATHSEPARATOR( *pDir ) || (*pDir == 0) ) ) ) ) - { - if ( PATHSEPARATOR( *pPath ) ) - { - pLastCommonPath = pPath + 1; - pLastCommonDir = pDir + 1; - } - if ( *pDir == 0 ) - { - --pLastCommonDir; - break; - } - ++pDir; ++pPath; - } - - // Nothing in common - if ( !pLastCommonPath ) - return false; - - // For each path separator remaining in the dir, need a ../ - int nOutLen = 0; - bool bLastCharWasSeparator = true; - for ( ; *pLastCommonDir; ++pLastCommonDir ) - { - if ( PATHSEPARATOR( *pLastCommonDir ) ) - { - pRelativePath[nOutLen++] = '.'; - pRelativePath[nOutLen++] = '.'; - pRelativePath[nOutLen++] = CORRECT_PATH_SEPARATOR; - bLastCharWasSeparator = true; - } - else - { - bLastCharWasSeparator = false; - } - } - - // Deal with relative paths not specified with a trailing slash - if ( !bLastCharWasSeparator ) - { - pRelativePath[nOutLen++] = '.'; - pRelativePath[nOutLen++] = '.'; - pRelativePath[nOutLen++] = CORRECT_PATH_SEPARATOR; - } - - // Copy the remaining part of the relative path over, fixing the path separators - for ( ; *pLastCommonPath; ++pLastCommonPath ) - { - if ( PATHSEPARATOR( *pLastCommonPath ) ) - { - pRelativePath[nOutLen++] = CORRECT_PATH_SEPARATOR; - } - else - { - pRelativePath[nOutLen++] = *pLastCommonPath; - } - - // Check for overflow - if ( nOutLen == nBufLen - 1 ) - break; - } - - pRelativePath[nOutLen] = 0; - return true; -} - - -//----------------------------------------------------------------------------- -// small helper function shared by lots of modules -//----------------------------------------------------------------------------- -bool V_IsAbsolutePath( const char *pStr ) -{ - bool bIsAbsolute = ( pStr[0] && pStr[1] == ':' ) || pStr[0] == '/' || pStr[0] == '\\'; - if ( IsX360() && !bIsAbsolute ) - { - bIsAbsolute = ( V_stristr( pStr, ":" ) != NULL ); - } - return bIsAbsolute; -} - - -// Copies at most nCharsToCopy bytes from pIn into pOut. -// Returns false if it would have overflowed pOut's buffer. -static bool CopyToMaxChars( char *pOut, int outSize, const char *pIn, int nCharsToCopy ) -{ - if ( outSize == 0 ) - return false; - - int iOut = 0; - while ( *pIn && nCharsToCopy > 0 ) - { - if ( iOut == (outSize-1) ) - { - pOut[iOut] = 0; - return false; - } - pOut[iOut] = *pIn; - ++iOut; - ++pIn; - --nCharsToCopy; - } - - pOut[iOut] = 0; - return true; -} - - -//----------------------------------------------------------------------------- -// Fixes up a file name, removing dot slashes, fixing slashes, converting to lowercase, etc. -//----------------------------------------------------------------------------- -void V_FixupPathName( char *pOut, size_t nOutLen, const char *pPath ) -{ - V_strncpy( pOut, pPath, nOutLen ); - V_FixSlashes( pOut ); - V_RemoveDotSlashes( pOut ); - V_FixDoubleSlashes( pOut ); - V_strlower( pOut ); -} - - -// Returns true if it completed successfully. -// If it would overflow pOut, it fills as much as it can and returns false. -bool V_StrSubst( - const char *pIn, - const char *pMatch, - const char *pReplaceWith, - char *pOut, - int outLen, - bool bCaseSensitive - ) -{ - int replaceFromLen = strlen( pMatch ); - int replaceToLen = strlen( pReplaceWith ); - - const char *pInStart = pIn; - char *pOutPos = pOut; - pOutPos[0] = 0; - - while ( 1 ) - { - int nRemainingOut = outLen - (pOutPos - pOut); - - const char *pTestPos = ( bCaseSensitive ? strstr( pInStart, pMatch ) : V_stristr( pInStart, pMatch ) ); - if ( pTestPos ) - { - // Found an occurence of pMatch. First, copy whatever leads up to the string. - int copyLen = pTestPos - pInStart; - if ( !CopyToMaxChars( pOutPos, nRemainingOut, pInStart, copyLen ) ) - return false; - - // Did we hit the end of the output string? - if ( copyLen > nRemainingOut-1 ) - return false; - - pOutPos += strlen( pOutPos ); - nRemainingOut = outLen - (pOutPos - pOut); - - // Now add the replacement string. - if ( !CopyToMaxChars( pOutPos, nRemainingOut, pReplaceWith, replaceToLen ) ) - return false; - - pInStart += copyLen + replaceFromLen; - pOutPos += replaceToLen; - } - else - { - // We're at the end of pIn. Copy whatever remains and get out. - int copyLen = strlen( pInStart ); - V_strncpy( pOutPos, pInStart, nRemainingOut ); - return ( copyLen <= nRemainingOut-1 ); - } - } -} - - -char* AllocString( const char *pStr, int nMaxChars ) -{ - int allocLen; - if ( nMaxChars == -1 ) - allocLen = strlen( pStr ) + 1; - else - allocLen = MIN( (int)strlen(pStr), nMaxChars ) + 1; - - char *pOut = new char[allocLen]; - V_strncpy( pOut, pStr, allocLen ); - return pOut; -} - - -void V_SplitString2( const char *pString, const char **pSeparators, int nSeparators, CUtlVector &outStrings ) -{ - outStrings.Purge(); - const char *pCurPos = pString; - while ( 1 ) - { - int iFirstSeparator = -1; - const char *pFirstSeparator = 0; - for ( int i=0; i < nSeparators; i++ ) - { - const char *pTest = V_stristr( pCurPos, pSeparators[i] ); - if ( pTest && (!pFirstSeparator || pTest < pFirstSeparator) ) - { - iFirstSeparator = i; - pFirstSeparator = pTest; - } - } - - if ( pFirstSeparator ) - { - // Split on this separator and continue on. - int separatorLen = strlen( pSeparators[iFirstSeparator] ); - if ( pFirstSeparator > pCurPos ) - { - outStrings.AddToTail( AllocString( pCurPos, pFirstSeparator-pCurPos ) ); - } - - pCurPos = pFirstSeparator + separatorLen; - } - else - { - // Copy the rest of the string - if ( strlen( pCurPos ) ) - { - outStrings.AddToTail( AllocString( pCurPos, -1 ) ); - } - return; - } - } -} - - -void V_SplitString( const char *pString, const char *pSeparator, CUtlVector &outStrings ) -{ - V_SplitString2( pString, &pSeparator, 1, outStrings ); -} - - -bool V_GetCurrentDirectory( char *pOut, int maxLen ) -{ -#if defined _LINUX || defined __APPLE__ - return getcwd( pOut, maxLen ) == pOut; -#else - return _getcwd( pOut, maxLen ) == pOut; -#endif -} - - -bool V_SetCurrentDirectory( const char *pDirName ) -{ -#if defined _LINUX || defined __APPLE__ - return chdir( pDirName ) == 0; -#else - return _chdir( pDirName ) == 0; -#endif -} - - -// This function takes a slice out of pStr and stores it in pOut. -// It follows the Python slice convention: -// Negative numbers wrap around the string (-1 references the last character). -// Numbers are clamped to the end of the string. -void V_StrSlice( const char *pStr, int firstChar, int lastCharNonInclusive, char *pOut, int outSize ) -{ - if ( outSize == 0 ) - return; - - int length = strlen( pStr ); - - // Fixup the string indices. - if ( firstChar < 0 ) - { - firstChar = length - (-firstChar % length); - } - else if ( firstChar >= length ) - { - pOut[0] = 0; - return; - } - - if ( lastCharNonInclusive < 0 ) - { - lastCharNonInclusive = length - (-lastCharNonInclusive % length); - } - else if ( lastCharNonInclusive > length ) - { - lastCharNonInclusive %= length; - } - - if ( lastCharNonInclusive <= firstChar ) - { - pOut[0] = 0; - return; - } - - int copyLen = lastCharNonInclusive - firstChar; - if ( copyLen <= (outSize-1) ) - { - memcpy( pOut, &pStr[firstChar], copyLen ); - pOut[copyLen] = 0; - } - else - { - memcpy( pOut, &pStr[firstChar], outSize-1 ); - pOut[outSize-1] = 0; - } -} - - -void V_StrLeft( const char *pStr, int nChars, char *pOut, int outSize ) -{ - if ( nChars == 0 ) - { - if ( outSize != 0 ) - pOut[0] = 0; - - return; - } - - V_StrSlice( pStr, 0, nChars, pOut, outSize ); -} - - -void V_StrRight( const char *pStr, int nChars, char *pOut, int outSize ) -{ - int len = strlen( pStr ); - if ( nChars >= len ) - { - V_strncpy( pOut, pStr, outSize ); - } - else - { - V_StrSlice( pStr, -nChars, strlen( pStr ), pOut, outSize ); - } -} - -//----------------------------------------------------------------------------- -// Convert multibyte to wchar + back -//----------------------------------------------------------------------------- -void V_strtowcs( const char *pString, int nInSize, wchar_t *pWString, int nOutSize ) -{ -#ifdef _WIN32 - if ( !MultiByteToWideChar( CP_UTF8, 0, pString, nInSize, pWString, nOutSize ) ) - { - *pWString = L'\0'; - } -#elif defined _LINUX || defined __APPLE__ - if ( mbstowcs( pWString, pString, nOutSize / sizeof(wchar_t) ) <= 0 ) - { - *pWString = 0; - } -#endif -} - -void V_wcstostr( const wchar_t *pWString, int nInSize, char *pString, int nOutSize ) -{ -#ifdef _WIN32 - if ( !WideCharToMultiByte( CP_UTF8, 0, pWString, nInSize, pString, nOutSize, NULL, NULL ) ) - { - *pString = '\0'; - } -#elif defined _LINUX || defined __APPLE__ - if ( wcstombs( pString, pWString, nOutSize ) <= 0 ) - { - *pString = '\0'; - } -#endif -} - - - -//-------------------------------------------------------------------------------- -// backslashification -//-------------------------------------------------------------------------------- - -static char s_BackSlashMap[]="\tt\nn\rr\"\"\\\\"; - -char *V_AddBackSlashesToSpecialChars( char const *pSrc ) -{ - // first, count how much space we are going to need - int nSpaceNeeded = 0; - for( char const *pScan = pSrc; *pScan; pScan++ ) - { - nSpaceNeeded++; - for(char const *pCharSet=s_BackSlashMap; *pCharSet; pCharSet += 2 ) - { - if ( *pCharSet == *pScan ) - nSpaceNeeded++; // we need to store a bakslash - } - } - char *pRet = new char[ nSpaceNeeded + 1 ]; // +1 for null - char *pOut = pRet; - - for( char const *pScan = pSrc; *pScan; pScan++ ) - { - bool bIsSpecial = false; - for(char const *pCharSet=s_BackSlashMap; *pCharSet; pCharSet += 2 ) - { - if ( *pCharSet == *pScan ) - { - *( pOut++ ) = '\\'; - *( pOut++ ) = pCharSet[1]; - bIsSpecial = true; - break; - } - } - if (! bIsSpecial ) - { - *( pOut++ ) = *pScan; - } - } - *( pOut++ ) = 0; - return pRet; -} diff --git a/tier1/tier1.vcxproj b/tier1/tier1.vcxproj index b973a72f..9ea23537 100644 --- a/tier1/tier1.vcxproj +++ b/tier1/tier1.vcxproj @@ -322,7 +322,6 @@ - diff --git a/tier1/tier1.vcxproj.filters b/tier1/tier1.vcxproj.filters index e5ee2758..f5866b6a 100644 --- a/tier1/tier1.vcxproj.filters +++ b/tier1/tier1.vcxproj.filters @@ -23,9 +23,6 @@ Source Files - - Source Files - Source Files