mirror of
https://github.com/alliedmodders/hl2sdk.git
synced 2025-01-03 16:13:22 +08:00
463 lines
19 KiB
C++
463 lines
19 KiB
C++
//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======//
|
|
//
|
|
// Purpose:
|
|
//
|
|
// $NoKeywords: $
|
|
//
|
|
//===========================================================================//
|
|
|
|
#ifndef TIER1_STRTOOLS_H
|
|
#define TIER1_STRTOOLS_H
|
|
|
|
#include "tier0/platform.h"
|
|
|
|
#ifdef _WIN32
|
|
#pragma once
|
|
#elif defined(_LINUX) || defined(__APPLE__)
|
|
#include <ctype.h>
|
|
#include <wchar.h>
|
|
#include <math.h>
|
|
#endif
|
|
|
|
#include <string.h>
|
|
#include <stdlib.h>
|
|
|
|
template< class T, class I > class CUtlMemory;
|
|
template< class T, class A > class CUtlVector;
|
|
|
|
#if defined(_LINUX) || defined(__APPLE__)
|
|
inline char *strupr( char *start )
|
|
{
|
|
char *str = start;
|
|
while( str && *str )
|
|
{
|
|
*str = (char)toupper(*str);
|
|
str++;
|
|
}
|
|
return start;
|
|
}
|
|
|
|
inline char *strlwr( char *start )
|
|
{
|
|
char *str = start;
|
|
while( str && *str )
|
|
{
|
|
*str = (char)tolower(*str);
|
|
str++;
|
|
}
|
|
return start;
|
|
}
|
|
|
|
#endif // _LINUX
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Portable versions of standard string functions
|
|
//-----------------------------------------------------------------------------
|
|
void _V_memset ( const char* file, int line, void *dest, int fill, int count );
|
|
void _V_memcpy ( const char* file, int line, void *dest, const void *src, int count );
|
|
void _V_memmove ( const char* file, int line, void *dest, const void *src, int count );
|
|
int _V_memcmp ( const char* file, int line, const void *m1, const void *m2, int count );
|
|
int _V_strlen ( const char* file, int line, const char *str );
|
|
void _V_strcpy ( const char* file, int line, char *dest, const char *src );
|
|
char* _V_strrchr ( const char* file, int line, const char *s, char c );
|
|
int _V_strcmp ( const char* file, int line, const char *s1, const char *s2 );
|
|
int _V_wcscmp ( const char* file, int line, const wchar_t *s1, const wchar_t *s2 );
|
|
int _V_stricmp ( const char* file, int line, const char *s1, const char *s2 );
|
|
char* _V_strstr ( const char* file, int line, const char *s1, const char *search );
|
|
char* _V_strupr ( const char* file, int line, char *start );
|
|
char* _V_strlower ( const char* file, int line, char *start );
|
|
int _V_wcslen ( const char* file, int line, const wchar_t *pwch );
|
|
|
|
|
|
#ifdef _DEBUG
|
|
|
|
#define V_memset(dest, fill, count) _V_memset (__FILE__, __LINE__, (dest), (fill), (count))
|
|
#define V_memcpy(dest, src, count) _V_memcpy (__FILE__, __LINE__, (dest), (src), (count))
|
|
#define V_memmove(dest, src, count) _V_memmove (__FILE__, __LINE__, (dest), (src), (count))
|
|
#define V_memcmp(m1, m2, count) _V_memcmp (__FILE__, __LINE__, (m1), (m2), (count))
|
|
#define V_strlen(str) _V_strlen (__FILE__, __LINE__, (str))
|
|
#define V_strcpy(dest, src) _V_strcpy (__FILE__, __LINE__, (dest), (src))
|
|
#define V_strrchr(s, c) _V_strrchr (__FILE__, __LINE__, (s), (c))
|
|
#define V_strcmp(s1, s2) _V_strcmp (__FILE__, __LINE__, (s1), (s2))
|
|
#define V_wcscmp(s1, s2) _V_wcscmp (__FILE__, __LINE__, (s1), (s2))
|
|
#define V_stricmp(s1, s2 ) _V_stricmp (__FILE__, __LINE__, (s1), (s2) )
|
|
#define V_strstr(s1, search ) _V_strstr (__FILE__, __LINE__, (s1), (search) )
|
|
#define V_strupr(start) _V_strupr (__FILE__, __LINE__, (start))
|
|
#define V_strlower(start) _V_strlower (__FILE__, __LINE__, (start))
|
|
#define V_wcslen(pwch) _V_wcslen (__FILE__, __LINE__, (pwch))
|
|
|
|
#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);
|
|
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; }
|
|
|
|
|
|
// 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 );
|
|
|
|
|
|
|
|
// 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, ... );
|
|
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);
|
|
|
|
|
|
// UNDONE: Find a non-compiler-specific way to do this
|
|
#ifdef _WIN32
|
|
#ifndef _VA_LIST_DEFINED
|
|
|
|
#ifdef _M_ALPHA
|
|
|
|
struct va_list
|
|
{
|
|
char *a0; /* pointer to first homed integer argument */
|
|
int offset; /* byte offset of next parameter */
|
|
};
|
|
|
|
#else // !_M_ALPHA
|
|
|
|
typedef char * va_list;
|
|
|
|
#endif // !_M_ALPHA
|
|
|
|
#define _VA_LIST_DEFINED
|
|
|
|
#endif // _VA_LIST_DEFINED
|
|
|
|
#elif defined(_LINUX) || defined(__APPLE__)
|
|
#include <stdarg.h>
|
|
#endif
|
|
|
|
#ifdef _WIN32
|
|
#define CORRECT_PATH_SEPARATOR '\\'
|
|
#define INCORRECT_PATH_SEPARATOR '/'
|
|
#elif defined(_LINUX) || defined(__APPLE__)
|
|
#define CORRECT_PATH_SEPARATOR '/'
|
|
#define INCORRECT_PATH_SEPARATOR '\\'
|
|
#endif
|
|
|
|
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 );
|
|
|
|
// 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 );
|
|
// Remove the final characters of ppath if it's '\' or '/'.
|
|
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 );
|
|
// Make path end with extension if it doesn't already have an extension
|
|
void V_DefaultExtension( char *path, const char *extension, int pathStringLength );
|
|
// Strips any current extension from path and ensures that extension is the new extension
|
|
void V_SetExtension( char *path, const char *extension, int pathStringLength );
|
|
// Removes any filename from path ( strips back to previous / or \ character )
|
|
void V_StripFilename( char *path );
|
|
// Remove the final directory from the path
|
|
bool V_StripLastDir( char *dirName, int maxlen );
|
|
// Returns a pointer to the unqualified file name (no path) of a file name
|
|
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 );
|
|
|
|
// 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 );
|
|
|
|
const char *V_GetFileExtension( 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 );
|
|
|
|
// 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 );
|
|
|
|
// 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 );
|
|
|
|
// 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 );
|
|
|
|
// 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 );
|
|
|
|
// Returns true if the path is an absolute path.
|
|
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 );
|
|
|
|
// 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<char*, CUtlMemory<char*, int> > &outStrings );
|
|
|
|
// Just like V_SplitString, but it can use multiple possible separators.
|
|
void V_SplitString2( const char *pString, const char **pSeparators, int nSeparators, CUtlVector<char*, CUtlMemory<char*, int> > &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 );
|
|
|
|
|
|
// 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 );
|
|
|
|
// Chop off the left nChars of a string.
|
|
void V_StrLeft( const char *pStr, int nChars, char *pOut, int outSize );
|
|
|
|
// Chop off the right nChars of a string.
|
|
void V_StrRight( const char *pStr, int nChars, char *pOut, int outSize );
|
|
|
|
// 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 );
|
|
|
|
// Force slashes of either type to be = separator character
|
|
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 );
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// generic unique name helper functions
|
|
//-----------------------------------------------------------------------------
|
|
|
|
// returns startindex if none found, 2 if "prefix" found, and n+1 if "prefixn" found
|
|
template < class NameArray >
|
|
int V_GenerateUniqueNameIndex( const char *prefix, const NameArray &nameArray, int startindex = 0 )
|
|
{
|
|
if ( prefix == NULL )
|
|
return 0;
|
|
|
|
int freeindex = startindex;
|
|
|
|
int nNames = nameArray.Count();
|
|
for ( int i = 0; i < nNames; ++i )
|
|
{
|
|
const char *pName = nameArray[ i ];
|
|
if ( !pName )
|
|
continue;
|
|
|
|
const char *pIndexStr = StringAfterPrefix( pName, prefix );
|
|
if ( pIndexStr )
|
|
{
|
|
int index = *pIndexStr ? atoi( pIndexStr ) : 1;
|
|
if ( index >= freeindex )
|
|
{
|
|
// TODO - check that there isn't more junk after the index in pElementName
|
|
freeindex = index + 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
return freeindex;
|
|
}
|
|
|
|
template < class NameArray >
|
|
bool V_GenerateUniqueName( char *name, int memsize, const char *prefix, const NameArray &nameArray )
|
|
{
|
|
if ( name == NULL || memsize == 0 )
|
|
return false;
|
|
|
|
if ( prefix == NULL )
|
|
{
|
|
name[ 0 ] = '\0';
|
|
return false;
|
|
}
|
|
|
|
int prefixLength = V_strlen( prefix );
|
|
if ( prefixLength + 1 > memsize )
|
|
{
|
|
name[ 0 ] = '\0';
|
|
return false;
|
|
}
|
|
|
|
int i = V_GenerateUniqueNameIndex( prefix, nameArray );
|
|
if ( i <= 0 )
|
|
{
|
|
V_strncpy( name, prefix, memsize );
|
|
return true;
|
|
}
|
|
|
|
int newlen = prefixLength + ( int )log10( ( float )i ) + 1;
|
|
if ( newlen + 1 > memsize )
|
|
{
|
|
V_strncpy( name, prefix, memsize );
|
|
return false;
|
|
}
|
|
|
|
V_snprintf( name, memsize, "%s%d", prefix, i );
|
|
return true;
|
|
}
|
|
|
|
|
|
|
|
// NOTE: This is for backward compatability!
|
|
// We need to DLL-export the Q methods in vstdlib but not link to them in other projects
|
|
#if !defined( VSTDLIB_BACKWARD_COMPAT )
|
|
|
|
#define Q_memset V_memset
|
|
#define Q_memcpy V_memcpy
|
|
#define Q_memmove V_memmove
|
|
#define Q_memcmp V_memcmp
|
|
#define Q_strlen V_strlen
|
|
#define Q_strcpy V_strcpy
|
|
#define Q_strrchr V_strrchr
|
|
#define Q_strcmp V_strcmp
|
|
#define Q_wcscmp V_wcscmp
|
|
#define Q_stricmp V_stricmp
|
|
#define Q_strstr V_strstr
|
|
#define Q_strupr V_strupr
|
|
#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_strnicmp V_strnicmp
|
|
#define Q_atoi V_atoi
|
|
#define Q_atof V_atof
|
|
#define Q_stristr V_stristr
|
|
#define Q_strnistr V_strnistr
|
|
#define Q_strnchr V_strnchr
|
|
#define Q_normalizeFloatString V_normalizeFloatString
|
|
#define Q_strncpy V_strncpy
|
|
#define Q_snprintf V_snprintf
|
|
#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_FileBase V_FileBase
|
|
#define Q_StripTrailingSlash V_StripTrailingSlash
|
|
#define Q_StripExtension V_StripExtension
|
|
#define Q_DefaultExtension V_DefaultExtension
|
|
#define Q_SetExtension V_SetExtension
|
|
#define Q_StripFilename V_StripFilename
|
|
#define Q_StripLastDir V_StripLastDir
|
|
#define Q_UnqualifiedFileName V_UnqualifiedFileName
|
|
#define Q_ComposeFileName V_ComposeFileName
|
|
#define Q_ExtractFilePath V_ExtractFilePath
|
|
#define Q_ExtractFileExtension V_ExtractFileExtension
|
|
#define Q_GetFileExtension V_GetFileExtension
|
|
#define Q_RemoveDotSlashes V_RemoveDotSlashes
|
|
#define Q_MakeAbsolutePath V_MakeAbsolutePath
|
|
#define Q_AppendSlash V_AppendSlash
|
|
#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_GenerateUniqueNameIndex V_GenerateUniqueNameIndex
|
|
#define Q_GenerateUniqueName V_GenerateUniqueName
|
|
#define Q_MakeRelativePath V_MakeRelativePath
|
|
|
|
#endif // !defined( VSTDLIB_DLL_EXPORT )
|
|
|
|
|
|
#endif // TIER1_STRTOOLS_H
|