150 lines
3.3 KiB
C++
150 lines
3.3 KiB
C++
//========= Copyright © Valve Corporation, All rights reserved. ============//
|
|
#include "pch_tier0.h"
|
|
|
|
// This function is marked in the VPC file as always being optimized, even in debug
|
|
// builds, because this gives a ~7% speedup on debug builds because this function is
|
|
// used by the debug allocator.
|
|
|
|
#define TOLOWERC( x ) (( ( x >= 'A' ) && ( x <= 'Z' ) )?( x + 32 ) : x )
|
|
|
|
#if !defined( STATIC_LINK )
|
|
#define FDECL extern "C"
|
|
#else
|
|
#define FDECL
|
|
#endif
|
|
|
|
FDECL int V_tier0_stricmp(const char *s1, const char *s2 )
|
|
{
|
|
// A string is always equal to itself. This optimization is
|
|
// surprisingly valuable.
|
|
if ( s1 == s2 )
|
|
return 0;
|
|
|
|
uint8 const *pS1 = ( uint8 const * ) s1;
|
|
uint8 const *pS2 = ( uint8 const * ) s2;
|
|
for(;;)
|
|
{
|
|
int c1 = *( pS1++ );
|
|
int c2 = *( pS2++ );
|
|
if ( c1 == c2 )
|
|
{
|
|
if ( !c1 ) return 0;
|
|
}
|
|
else
|
|
{
|
|
if ( ! c2 )
|
|
{
|
|
return c1 - c2;
|
|
}
|
|
c1 = TOLOWERC( c1 );
|
|
c2 = TOLOWERC( c2 );
|
|
if ( c1 != c2 )
|
|
{
|
|
return c1 - c2;
|
|
}
|
|
}
|
|
c1 = *( pS1++ );
|
|
c2 = *( pS2++ );
|
|
if ( c1 == c2 )
|
|
{
|
|
if ( !c1 ) return 0;
|
|
}
|
|
else
|
|
{
|
|
if ( ! c2 )
|
|
{
|
|
return c1 - c2;
|
|
}
|
|
c1 = TOLOWERC( c1 );
|
|
c2 = TOLOWERC( c2 );
|
|
if ( c1 != c2 )
|
|
{
|
|
return c1 - c2;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
FDECL void V_tier0_strncpy( char *a, const char *b, int n )
|
|
{
|
|
Assert( n >= sizeof( *a ) );
|
|
|
|
// NOTE: Never never use strncpy! Here's what it actually does, which is not what we want!
|
|
|
|
// (from MSDN)
|
|
// The strncpy function copies the initial count characters of strSource to strDest
|
|
// and returns strDest. If count is less than or equal to the length of strSource,
|
|
// a null character is not appended automatically to the copied string. If count
|
|
// is greater than the length of strSource, the destination string is padded with
|
|
// null characters up to length count. The behavior of strncpy is undefined
|
|
// if the source and destination strings overlap.
|
|
// strncpy( pDest, pSrc, maxLen );
|
|
|
|
char *pLast = a + n - 1;
|
|
while ( (a < pLast) && (*b != 0) )
|
|
{
|
|
*a = *b;
|
|
++a; ++b;
|
|
}
|
|
*a = 0;
|
|
}
|
|
|
|
FDECL char *V_tier0_strncat( char *pDest, const char *pSrc, int destBufferSize, int max_chars_to_copy )
|
|
{
|
|
int charstocopy = 0;
|
|
|
|
Assert( destBufferSize >= 0 );
|
|
|
|
int len = (int)strlen(pDest);
|
|
int srclen = (int)strlen( pSrc );
|
|
if ( max_chars_to_copy <= -1 )
|
|
{
|
|
charstocopy = srclen;
|
|
}
|
|
else
|
|
{
|
|
charstocopy = Min( max_chars_to_copy, (int)srclen );
|
|
}
|
|
|
|
if ( len + charstocopy >= destBufferSize )
|
|
{
|
|
charstocopy = destBufferSize - len - 1;
|
|
}
|
|
|
|
// charstocopy can end up negative if you fill a buffer and then pass in a smaller
|
|
// buffer size. Yes, this actually happens.
|
|
// Cast to ptrdiff_t is necessary in order to check for negative (size_t is unsigned)
|
|
if ( charstocopy <= 0 )
|
|
{
|
|
return pDest;
|
|
}
|
|
|
|
ANALYZE_SUPPRESS( 6059 ); // warning C6059: : Incorrect length parameter in call to 'strncat'. Pass the number of remaining characters, not the buffer size of 'argument 1'
|
|
char *pOut = strncat( pDest, pSrc, charstocopy );
|
|
return pOut;
|
|
}
|
|
|
|
FDECL int V_tier0_vsnprintf( char *a, int n, const char *f, va_list l )
|
|
{
|
|
int len = _vsnprintf( a, n, f, l );
|
|
|
|
if ( ( len < 0 ) ||
|
|
( n > 0 && len >= n ) )
|
|
{
|
|
len = n - 1;
|
|
a[n - 1] = 0;
|
|
}
|
|
|
|
return len;
|
|
}
|
|
|
|
FDECL int V_tier0_snprintf( char *a, int n, const char *f, ... )
|
|
{
|
|
va_list l;
|
|
|
|
va_start( l, f );
|
|
int len = V_tier0_vsnprintf( a, n, f, l );
|
|
va_end( l );
|
|
return len;
|
|
}
|