1101 lines
28 KiB
C
1101 lines
28 KiB
C
|
|
||
|
#ifndef __STR_H__
|
||
|
#define __STR_H__
|
||
|
|
||
|
/*
|
||
|
===============================================================================
|
||
|
|
||
|
Character string
|
||
|
|
||
|
===============================================================================
|
||
|
*/
|
||
|
|
||
|
// these library functions should not be used for cross platform compatibility
|
||
|
#define strcmp idStr::Cmp // use_idStr_Cmp
|
||
|
#define strncmp use_idStr_Cmpn
|
||
|
#define StrCmpN use_idStr_Cmpn
|
||
|
#define strcmpi use_idStr_Icmp
|
||
|
#define StrCmpI use_idStr_Icmp
|
||
|
#define stricmp idStr::Icmp // use_idStr_Icmp
|
||
|
#define _stricmp use_idStr_Icmp
|
||
|
#define strcasecmp use_idStr_Icmp
|
||
|
#define strnicmp use_idStr_Icmpn
|
||
|
#define _strnicmp use_idStr_Icmpn
|
||
|
#define _memicmp use_idStr_Icmpn
|
||
|
#define StrCmpNI use_idStr_Icmpn
|
||
|
#define snprintf use_idStr_snPrintf
|
||
|
#define _snprintf use_idStr_snPrintf
|
||
|
#define vsnprintf use_idStr_vsnPrintf
|
||
|
#define _vsnprintf use_idStr_vsnPrintf
|
||
|
|
||
|
#ifdef _XENON
|
||
|
class __declspec(align(16)) idVec4;
|
||
|
#else
|
||
|
class idVec4;
|
||
|
#endif
|
||
|
|
||
|
#ifndef FILE_HASH_SIZE
|
||
|
#define FILE_HASH_SIZE 1024
|
||
|
#endif
|
||
|
|
||
|
// color escape character
|
||
|
const int C_COLOR_ESCAPE = '^';
|
||
|
const int C_COLOR_DEFAULT = '0';
|
||
|
const int C_COLOR_RED = '1';
|
||
|
const int C_COLOR_GREEN = '2';
|
||
|
const int C_COLOR_YELLOW = '3';
|
||
|
const int C_COLOR_BLUE = '4';
|
||
|
const int C_COLOR_CYAN = '5';
|
||
|
const int C_COLOR_MAGENTA = '6';
|
||
|
const int C_COLOR_WHITE = '7';
|
||
|
const int C_COLOR_GRAY = '8';
|
||
|
const int C_COLOR_BLACK = '9';
|
||
|
// RAVEN BEGIN
|
||
|
// bdube: added
|
||
|
const int C_COLOR_CONSOLE = ':';
|
||
|
// RAVEN END
|
||
|
|
||
|
// color escape string
|
||
|
#define S_COLOR_DEFAULT "^0"
|
||
|
#define S_COLOR_RED "^1"
|
||
|
#define S_COLOR_GREEN "^2"
|
||
|
#define S_COLOR_YELLOW "^3"
|
||
|
#define S_COLOR_BLUE "^4"
|
||
|
#define S_COLOR_CYAN "^5"
|
||
|
#define S_COLOR_MAGENTA "^6"
|
||
|
#define S_COLOR_WHITE "^7"
|
||
|
#define S_COLOR_GRAY "^8"
|
||
|
#define S_COLOR_BLACK "^9"
|
||
|
// RAVEN BEGIN
|
||
|
// bdube: added
|
||
|
#define S_COLOR_CONSOLE "^:"
|
||
|
// ddynerman: team colors
|
||
|
#define S_COLOR_MARINE "^c683"
|
||
|
#define S_COLOR_STROGG "^c950"
|
||
|
#define S_COLOR_ALERT "^c920"
|
||
|
// ddynerman: MP icons
|
||
|
#define I_VOICE_ENABLED "^ivce"
|
||
|
#define I_VOICE_DISABLED "^ivcd"
|
||
|
#define I_FRIEND_ENABLED "^ifde"
|
||
|
#define I_FRIEND_DISABLED "^ifdd"
|
||
|
#define I_FLAG_MARINE "^iflm"
|
||
|
#define I_FLAG_STROGG "^ifls"
|
||
|
#define I_READY "^iyrd"
|
||
|
#define I_NOT_READY "^inrd"
|
||
|
// shouchard: server browser stuff
|
||
|
#define I_SERVER_DEDICATED "^ids0"
|
||
|
#define I_SERVER_DEDICATED_PB "^idsp"
|
||
|
#define I_SERVER_LOCKED "^isl0"
|
||
|
#define I_SERVER_FAVORITE "^isf0"
|
||
|
const int VA_BUF_LEN = 16384;
|
||
|
const int VA_NUM_BUFS = 8;
|
||
|
// RAVEN END
|
||
|
|
||
|
// make idStr a multiple of 16 bytes long
|
||
|
// don't make too large to keep memory requirements to a minimum
|
||
|
const int STR_ALLOC_BASE = 20;
|
||
|
const int STR_ALLOC_GRAN = 32;
|
||
|
|
||
|
typedef enum {
|
||
|
MEASURE_SIZE = 0,
|
||
|
MEASURE_BANDWIDTH
|
||
|
} Measure_t;
|
||
|
|
||
|
// RAVEN BEGIN
|
||
|
// bdube: string escape codes
|
||
|
#define S_ESCAPE_UNKNOWN BIT(0)
|
||
|
#define S_ESCAPE_COLOR BIT(1)
|
||
|
#define S_ESCAPE_COLORINDEX BIT(2)
|
||
|
#define S_ESCAPE_ICON BIT(3)
|
||
|
#define S_ESCAPE_COMMAND BIT(4)
|
||
|
#define S_ESCAPE_ALL ( S_ESCAPE_COLOR | S_ESCAPE_COLORINDEX | S_ESCAPE_ICON | S_ESCAPE_COMMAND )
|
||
|
// RAVEN END
|
||
|
|
||
|
class idStr {
|
||
|
|
||
|
public:
|
||
|
idStr( void );
|
||
|
idStr( const idStr &text );
|
||
|
idStr( const idStr &text, int start, int end );
|
||
|
idStr( const char *text );
|
||
|
idStr( const char *text, int start, int end );
|
||
|
explicit idStr( const bool b );
|
||
|
explicit idStr( const char c );
|
||
|
explicit idStr( const int i );
|
||
|
explicit idStr( const unsigned u );
|
||
|
explicit idStr( const float f );
|
||
|
~idStr( void );
|
||
|
|
||
|
size_t Size( void ) const;
|
||
|
const char * c_str( void ) const;
|
||
|
operator const char *( void ) const;
|
||
|
operator const char *( void );
|
||
|
|
||
|
char operator[]( int index ) const;
|
||
|
char & operator[]( int index );
|
||
|
|
||
|
void operator=( const idStr &text );
|
||
|
void operator=( const char *text );
|
||
|
|
||
|
friend idStr operator+( const idStr &a, const idStr &b );
|
||
|
friend idStr operator+( const idStr &a, const char *b );
|
||
|
friend idStr operator+( const char *a, const idStr &b );
|
||
|
|
||
|
friend idStr operator+( const idStr &a, const float b );
|
||
|
friend idStr operator+( const idStr &a, const int b );
|
||
|
friend idStr operator+( const idStr &a, const unsigned b );
|
||
|
friend idStr operator+( const idStr &a, const bool b );
|
||
|
friend idStr operator+( const idStr &a, const char b );
|
||
|
|
||
|
idStr & operator+=( const idStr &a );
|
||
|
idStr & operator+=( const char *a );
|
||
|
idStr & operator+=( const float a );
|
||
|
idStr & operator+=( const char a );
|
||
|
idStr & operator+=( const int a );
|
||
|
idStr & operator+=( const unsigned a );
|
||
|
idStr & operator+=( const bool a );
|
||
|
|
||
|
// case sensitive compare
|
||
|
friend bool operator==( const idStr &a, const idStr &b );
|
||
|
friend bool operator==( const idStr &a, const char *b );
|
||
|
friend bool operator==( const char *a, const idStr &b );
|
||
|
|
||
|
// case sensitive compare
|
||
|
friend bool operator!=( const idStr &a, const idStr &b );
|
||
|
friend bool operator!=( const idStr &a, const char *b );
|
||
|
friend bool operator!=( const char *a, const idStr &b );
|
||
|
|
||
|
// case sensitive compare
|
||
|
int Cmp( const char *text ) const;
|
||
|
int Cmpn( const char *text, int n ) const;
|
||
|
int CmpPrefix( const char *text ) const;
|
||
|
|
||
|
// case insensitive compare
|
||
|
int Icmp( const char *text ) const;
|
||
|
int Icmpn( const char *text, int n ) const;
|
||
|
int IcmpPrefix( const char *text ) const;
|
||
|
|
||
|
// case insensitive compare ignoring color
|
||
|
// RAVEN BEGIN
|
||
|
// bdube: changed to escapes
|
||
|
int IcmpNoEscape( const char *text ) const;
|
||
|
// RAVEN END
|
||
|
|
||
|
// compares paths and makes sure folders come first
|
||
|
int IcmpPath( const char *text ) const;
|
||
|
int IcmpnPath( const char *text, int n ) const;
|
||
|
int IcmpPrefixPath( const char *text ) const;
|
||
|
|
||
|
int Length( void ) const;
|
||
|
int Allocated( void ) const;
|
||
|
void Empty( void );
|
||
|
bool IsEmpty( void ) const;
|
||
|
void Clear( void );
|
||
|
void Append( const char a );
|
||
|
void Append( const idStr &text );
|
||
|
void Append( const char *text );
|
||
|
void Append( const char *text, int len );
|
||
|
void Insert( const char a, int index );
|
||
|
void Insert( const char *text, int index );
|
||
|
void ToLower( void );
|
||
|
void ToUpper( void );
|
||
|
bool IsNumeric( void ) const;
|
||
|
bool HasLower( void ) const;
|
||
|
bool HasUpper( void ) const;
|
||
|
// RAVEN BEGIN
|
||
|
// bdube: escapes
|
||
|
int IsEscape( int* type = NULL ) const;
|
||
|
int LengthWithoutEscapes ( void ) const;
|
||
|
idStr & RemoveEscapes ( int escapes = S_ESCAPE_ALL );
|
||
|
// RAVEN END
|
||
|
void CapLength( int );
|
||
|
void Fill( const char ch, int newlen );
|
||
|
int Find( const char c, int start = 0, int end = -1 ) const;
|
||
|
int Find( const char *text, bool casesensitive = true, int start = 0, int end = -1 ) const;
|
||
|
bool Filter( const char *filter, bool casesensitive = true ) const;
|
||
|
int Last( const char c ) const; // return the index to the last occurance of 'c', returns -1 if not found
|
||
|
const char * Left( int len, idStr &result ) const; // store the leftmost 'len' characters in the result
|
||
|
const char * Right( int len, idStr &result ) const; // store the rightmost 'len' characters in the result
|
||
|
const char * Mid( int start, int len, idStr &result ) const; // store 'len' characters starting at 'start' in result
|
||
|
idStr Left( int len ) const; // return the leftmost 'len' characters
|
||
|
idStr Right( int len ) const; // return the rightmost 'len' characters
|
||
|
idStr Mid( int start, int len ) const; // return 'len' characters starting at 'start'
|
||
|
void StripLeading( const char c ); // strip char from front as many times as the char occurs
|
||
|
void StripLeading( const char *string ); // strip string from front as many times as the string occurs
|
||
|
bool StripLeadingOnce( const char *string ); // strip string from front just once if it occurs
|
||
|
void StripTrailing( const char c ); // strip char from end as many times as the char occurs
|
||
|
void StripTrailing( const char *string ); // strip string from end as many times as the string occurs
|
||
|
bool StripTrailingOnce( const char *string ); // strip string from end just once if it occurs
|
||
|
void Strip( const char c ); // strip char from front and end as many times as the char occurs
|
||
|
void Strip( const char *string ); // strip string from front and end as many times as the string occurs
|
||
|
void StripTrailingWhitespace( void ); // strip trailing white space characters
|
||
|
// RAVEN BEGIN
|
||
|
void StripUntil( const char c ); // strip until this character is reached or there is no string left
|
||
|
// RAVEN END
|
||
|
idStr & StripQuotes( void ); // strip quotes around string
|
||
|
// RAVEN BEGIN
|
||
|
// scork: added replacement-count return
|
||
|
int Replace( const char *old, const char *nw );
|
||
|
// RAVEN END
|
||
|
|
||
|
|
||
|
// file name methods
|
||
|
int FileNameHash( void ) const; // hash key for the filename (skips extension)
|
||
|
idStr & BackSlashesToSlashes( void ); // convert slashes
|
||
|
// RAVEN BEGIN
|
||
|
// jscott:
|
||
|
idStr & SlashesToBackSlashes( void ); // convert slashes
|
||
|
// nmckenzie: char swapping routine
|
||
|
bool HasChar( const char check );
|
||
|
bool HasChars( const char *check );
|
||
|
idStr & ReplaceChar( const char from, const char to );
|
||
|
idStr & ReplaceChars( const char *from, const char to );
|
||
|
// RAVEN END
|
||
|
idStr & SetFileExtension( const char *extension ); // set the given file extension
|
||
|
idStr & StripFileExtension( void ); // remove any file extension
|
||
|
idStr & StripAbsoluteFileExtension( void ); // remove any file extension looking from front (useful if there are multiple .'s)
|
||
|
idStr & DefaultFileExtension( const char *extension ); // if there's no file extension use the default
|
||
|
idStr & DefaultPath( const char *basepath ); // if there's no path use the default
|
||
|
void AppendPath( const char *text ); // append a partial path
|
||
|
idStr & StripFilename( void ); // remove the filename from a path
|
||
|
idStr & StripPath( void ); // remove the path from the filename
|
||
|
void ExtractFilePath( idStr &dest ) const; // copy the file path to another string
|
||
|
void ExtractFileName( idStr &dest ) const; // copy the filename to another string
|
||
|
void ExtractFileBase( idStr &dest ) const; // copy the filename minus the extension to another string
|
||
|
void ExtractFileExtension( idStr &dest ) const; // copy the file extension to another string
|
||
|
bool CheckExtension( const char *ext );
|
||
|
void ScrubFileName( void ); // Turns a bad file name into a good one or your money back
|
||
|
|
||
|
// RAVEN BEGIN
|
||
|
// jscott: like the declManager version, but globally accessable
|
||
|
void MakeNameCanonical( void );
|
||
|
void EnsurePrintable( void );
|
||
|
// RAVEN END
|
||
|
|
||
|
// RAVEN BEGIN
|
||
|
// abahr
|
||
|
void Split( idList<idStr>& list, const char delimiter = ',', const char groupDelimiter = '\'' );
|
||
|
// RAVEN END
|
||
|
|
||
|
// char * methods to replace library functions
|
||
|
static int Length( const char *s );
|
||
|
static char * ToLower( char *s );
|
||
|
static char * ToUpper( char *s );
|
||
|
static bool IsNumeric( const char *s );
|
||
|
static bool HasLower( const char *s );
|
||
|
static bool HasUpper( const char *s );
|
||
|
// RAVEN BEGIN
|
||
|
// bdube: escape codes
|
||
|
static int IsEscape( const char *s, int* type = NULL );
|
||
|
static int LengthWithoutEscapes( const char *s );
|
||
|
static char * RemoveEscapes( char *s, int escapes = S_ESCAPE_ALL );
|
||
|
// RAVEN END
|
||
|
static int Cmp( const char *s1, const char *s2 );
|
||
|
static int Cmpn( const char *s1, const char *s2, int n );
|
||
|
static int Icmp( const char *s1, const char *s2 );
|
||
|
static int Icmpn( const char *s1, const char *s2, int n );
|
||
|
// RAVEN BEGIN
|
||
|
// bdube: escapes
|
||
|
static int IcmpNoEscape( const char *s1, const char *s2 );
|
||
|
// RAVEN END
|
||
|
static int IcmpPath( const char *s1, const char *s2 ); // compares paths and makes sure folders come first
|
||
|
static int IcmpnPath( const char *s1, const char *s2, int n ); // compares paths and makes sure folders come first
|
||
|
static void Append( char *dest, int size, const char *src );
|
||
|
static void Copynz( char *dest, const char *src, int destsize );
|
||
|
static int snPrintf( char *dest, int size, const char *fmt, ... ) id_attribute((format(printf,3,4)));
|
||
|
static int vsnPrintf( char *dest, int size, const char *fmt, va_list argptr );
|
||
|
static int FindChar( const char *str, const char c, int start = 0, int end = -1 );
|
||
|
static int FindText( const char *str, const char *text, bool casesensitive = true, int start = 0, int end = -1 );
|
||
|
static bool Filter( const char *filter, const char *name, bool casesensitive );
|
||
|
static void StripMediaName( const char *name, idStr &mediaName );
|
||
|
static bool CheckExtension( const char *name, const char *ext );
|
||
|
static const char * FloatArrayToString( const float *array, const int length, const int precision );
|
||
|
|
||
|
// hash keys
|
||
|
static int Hash( const char *string );
|
||
|
static int Hash( const char *string, int length );
|
||
|
static int IHash( const char *string ); // case insensitive
|
||
|
static int IHash( const char *string, int length ); // case insensitive
|
||
|
|
||
|
// character methods
|
||
|
static char ToLower( byte c );
|
||
|
static char ToUpper( byte c );
|
||
|
static bool CharIsPrintable( byte c );
|
||
|
static bool CharIsLower( byte c );
|
||
|
static bool CharIsUpper( byte c );
|
||
|
static bool CharIsAlpha( byte c );
|
||
|
static bool CharIsNumeric( byte c );
|
||
|
static bool CharIsNewLine( byte c );
|
||
|
static bool CharIsTab( byte c );
|
||
|
static int ColorIndex( int c );
|
||
|
static idVec4 & ColorForIndex( int i );
|
||
|
|
||
|
friend int sprintf( idStr &dest, const char *fmt, ... );
|
||
|
friend int vsprintf( idStr &dest, const char *fmt, va_list ap );
|
||
|
|
||
|
void ReAllocate( int amount, bool keepold ); // reallocate string data buffer
|
||
|
void FreeData( void ); // free allocated string memory
|
||
|
|
||
|
// format value in the given measurement with the best unit, returns the best unit
|
||
|
int BestUnit( const char *format, float value, Measure_t measure );
|
||
|
// format value in the requested unit and measurement
|
||
|
void SetUnit( const char *format, float value, int unit, Measure_t measure );
|
||
|
|
||
|
static void InitMemory( void );
|
||
|
static void ShutdownMemory( void );
|
||
|
static void PurgeMemory( void );
|
||
|
static void ShowMemoryUsage_f( const idCmdArgs &args );
|
||
|
|
||
|
int DynamicMemoryUsed() const;
|
||
|
static idStr FormatNumber( int number );
|
||
|
|
||
|
static void Split( const char* source, idList<idStr>& list, const char delimiter = ',', const char groupDelimiter = '\'' );
|
||
|
|
||
|
idStr GetLastColorCode( void ) const;
|
||
|
|
||
|
protected:
|
||
|
int len;
|
||
|
char * data;
|
||
|
int alloced;
|
||
|
char baseBuffer[ STR_ALLOC_BASE ];
|
||
|
|
||
|
void Init( void ); // initialize string using base buffer
|
||
|
void EnsureAlloced( int amount, bool keepold = true ); // ensure string data buffer is large anough
|
||
|
|
||
|
// RAVEN BEGIN
|
||
|
public:
|
||
|
static const bool printableCharacter[256];
|
||
|
static const char upperCaseCharacter[256];
|
||
|
static const char lowerCaseCharacter[256];
|
||
|
// RAVEN END
|
||
|
};
|
||
|
|
||
|
char * va( const char *fmt, ... ) id_attribute((format(printf,1,2)));
|
||
|
|
||
|
// RAVEN BEGIN
|
||
|
// abahr
|
||
|
char* fe( int errorId );
|
||
|
// RAVEN END
|
||
|
|
||
|
ID_INLINE void idStr::EnsureAlloced( int amount, bool keepold ) {
|
||
|
if ( amount > alloced ) {
|
||
|
ReAllocate( amount, keepold );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
ID_INLINE void idStr::Init( void ) {
|
||
|
len = 0;
|
||
|
alloced = STR_ALLOC_BASE;
|
||
|
data = baseBuffer;
|
||
|
data[ 0 ] = '\0';
|
||
|
#ifdef ID_DEBUG_MEMORY
|
||
|
memset( baseBuffer, 0, sizeof( baseBuffer ) );
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
ID_INLINE idStr::idStr( void ) {
|
||
|
Init();
|
||
|
}
|
||
|
|
||
|
ID_INLINE idStr::idStr( const idStr &text ) {
|
||
|
int l;
|
||
|
|
||
|
Init();
|
||
|
l = text.Length();
|
||
|
EnsureAlloced( l + 1 );
|
||
|
strcpy( data, text.data );
|
||
|
len = l;
|
||
|
}
|
||
|
|
||
|
ID_INLINE idStr::idStr( const idStr &text, int start, int end ) {
|
||
|
int i;
|
||
|
int l;
|
||
|
|
||
|
Init();
|
||
|
if ( end > text.Length() ) {
|
||
|
end = text.Length();
|
||
|
}
|
||
|
if ( start > text.Length() ) {
|
||
|
start = text.Length();
|
||
|
} else if ( start < 0 ) {
|
||
|
start = 0;
|
||
|
}
|
||
|
|
||
|
l = end - start;
|
||
|
if ( l < 0 ) {
|
||
|
l = 0;
|
||
|
}
|
||
|
|
||
|
EnsureAlloced( l + 1 );
|
||
|
|
||
|
for ( i = 0; i < l; i++ ) {
|
||
|
data[ i ] = text[ start + i ];
|
||
|
}
|
||
|
|
||
|
data[ l ] = '\0';
|
||
|
len = l;
|
||
|
}
|
||
|
|
||
|
ID_INLINE idStr::idStr( const char *text ) {
|
||
|
int l;
|
||
|
|
||
|
Init();
|
||
|
if ( text ) {
|
||
|
l = strlen( text );
|
||
|
EnsureAlloced( l + 1 );
|
||
|
strcpy( data, text );
|
||
|
len = l;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
ID_INLINE idStr::idStr( const char *text, int start, int end ) {
|
||
|
int i;
|
||
|
int l = strlen( text );
|
||
|
|
||
|
Init();
|
||
|
if ( end > l ) {
|
||
|
end = l;
|
||
|
}
|
||
|
if ( start > l ) {
|
||
|
start = l;
|
||
|
} else if ( start < 0 ) {
|
||
|
start = 0;
|
||
|
}
|
||
|
|
||
|
l = end - start;
|
||
|
if ( l < 0 ) {
|
||
|
l = 0;
|
||
|
}
|
||
|
|
||
|
EnsureAlloced( l + 1 );
|
||
|
|
||
|
for ( i = 0; i < l; i++ ) {
|
||
|
data[ i ] = text[ start + i ];
|
||
|
}
|
||
|
|
||
|
data[ l ] = '\0';
|
||
|
len = l;
|
||
|
}
|
||
|
|
||
|
ID_INLINE idStr::idStr( const bool b ) {
|
||
|
Init();
|
||
|
EnsureAlloced( 2 );
|
||
|
data[ 0 ] = b ? '1' : '0';
|
||
|
data[ 1 ] = '\0';
|
||
|
len = 1;
|
||
|
}
|
||
|
|
||
|
ID_INLINE idStr::idStr( const char c ) {
|
||
|
Init();
|
||
|
EnsureAlloced( 2 );
|
||
|
data[ 0 ] = c;
|
||
|
data[ 1 ] = '\0';
|
||
|
len = 1;
|
||
|
}
|
||
|
|
||
|
ID_INLINE idStr::idStr( const int i ) {
|
||
|
char text[ 64 ];
|
||
|
int l;
|
||
|
|
||
|
Init();
|
||
|
l = sprintf( text, "%d", i );
|
||
|
EnsureAlloced( l + 1 );
|
||
|
strcpy( data, text );
|
||
|
len = l;
|
||
|
}
|
||
|
|
||
|
ID_INLINE idStr::idStr( const unsigned u ) {
|
||
|
char text[ 64 ];
|
||
|
int l;
|
||
|
|
||
|
Init();
|
||
|
l = sprintf( text, "%u", u );
|
||
|
EnsureAlloced( l + 1 );
|
||
|
strcpy( data, text );
|
||
|
len = l;
|
||
|
}
|
||
|
|
||
|
ID_INLINE idStr::idStr( const float f ) {
|
||
|
char text[ 64 ];
|
||
|
int l;
|
||
|
|
||
|
Init();
|
||
|
l = idStr::snPrintf( text, sizeof( text ), "%f", f );
|
||
|
while( l > 0 && text[l-1] == '0' ) text[--l] = '\0';
|
||
|
while( l > 0 && text[l-1] == '.' ) text[--l] = '\0';
|
||
|
EnsureAlloced( l + 1 );
|
||
|
strcpy( data, text );
|
||
|
len = l;
|
||
|
}
|
||
|
|
||
|
ID_INLINE idStr::~idStr( void ) {
|
||
|
FreeData();
|
||
|
}
|
||
|
|
||
|
ID_INLINE size_t idStr::Size( void ) const {
|
||
|
return sizeof( *this ) + Allocated();
|
||
|
}
|
||
|
|
||
|
ID_INLINE const char *idStr::c_str( void ) const {
|
||
|
return data;
|
||
|
}
|
||
|
|
||
|
ID_INLINE idStr::operator const char *( void ) {
|
||
|
return c_str();
|
||
|
}
|
||
|
|
||
|
ID_INLINE idStr::operator const char *( void ) const {
|
||
|
return c_str();
|
||
|
}
|
||
|
|
||
|
ID_INLINE char idStr::operator[]( int index ) const {
|
||
|
assert( ( index >= 0 ) && ( index <= len ) );
|
||
|
return data[ index ];
|
||
|
}
|
||
|
|
||
|
ID_INLINE char &idStr::operator[]( int index ) {
|
||
|
assert( ( index >= 0 ) && ( index <= len ) );
|
||
|
return data[ index ];
|
||
|
}
|
||
|
|
||
|
ID_INLINE void idStr::operator=( const idStr &text ) {
|
||
|
int l;
|
||
|
|
||
|
l = text.Length();
|
||
|
EnsureAlloced( l + 1, false );
|
||
|
memcpy( data, text.data, l );
|
||
|
data[l] = '\0';
|
||
|
len = l;
|
||
|
}
|
||
|
|
||
|
ID_INLINE idStr operator+( const idStr &a, const idStr &b ) {
|
||
|
idStr result( a );
|
||
|
result.Append( b );
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
ID_INLINE idStr operator+( const idStr &a, const char *b ) {
|
||
|
idStr result( a );
|
||
|
result.Append( b );
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
ID_INLINE idStr operator+( const char *a, const idStr &b ) {
|
||
|
idStr result( a );
|
||
|
result.Append( b );
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
ID_INLINE idStr operator+( const idStr &a, const bool b ) {
|
||
|
idStr result( a );
|
||
|
result.Append( b ? "true" : "false" );
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
ID_INLINE idStr operator+( const idStr &a, const char b ) {
|
||
|
idStr result( a );
|
||
|
result.Append( b );
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
ID_INLINE idStr operator+( const idStr &a, const float b ) {
|
||
|
char text[ 64 ];
|
||
|
idStr result( a );
|
||
|
|
||
|
sprintf( text, "%f", b );
|
||
|
result.Append( text );
|
||
|
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
ID_INLINE idStr operator+( const idStr &a, const int b ) {
|
||
|
char text[ 64 ];
|
||
|
idStr result( a );
|
||
|
|
||
|
sprintf( text, "%d", b );
|
||
|
result.Append( text );
|
||
|
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
ID_INLINE idStr operator+( const idStr &a, const unsigned b ) {
|
||
|
char text[ 64 ];
|
||
|
idStr result( a );
|
||
|
|
||
|
sprintf( text, "%u", b );
|
||
|
result.Append( text );
|
||
|
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
ID_INLINE idStr &idStr::operator+=( const float a ) {
|
||
|
char text[ 64 ];
|
||
|
|
||
|
sprintf( text, "%f", a );
|
||
|
Append( text );
|
||
|
|
||
|
return *this;
|
||
|
}
|
||
|
|
||
|
ID_INLINE idStr &idStr::operator+=( const int a ) {
|
||
|
char text[ 64 ];
|
||
|
|
||
|
sprintf( text, "%d", a );
|
||
|
Append( text );
|
||
|
|
||
|
return *this;
|
||
|
}
|
||
|
|
||
|
ID_INLINE idStr &idStr::operator+=( const unsigned a ) {
|
||
|
char text[ 64 ];
|
||
|
|
||
|
sprintf( text, "%u", a );
|
||
|
Append( text );
|
||
|
|
||
|
return *this;
|
||
|
}
|
||
|
|
||
|
ID_INLINE idStr &idStr::operator+=( const idStr &a ) {
|
||
|
Append( a );
|
||
|
return *this;
|
||
|
}
|
||
|
|
||
|
ID_INLINE idStr &idStr::operator+=( const char *a ) {
|
||
|
Append( a );
|
||
|
return *this;
|
||
|
}
|
||
|
|
||
|
ID_INLINE idStr &idStr::operator+=( const char a ) {
|
||
|
Append( a );
|
||
|
return *this;
|
||
|
}
|
||
|
|
||
|
ID_INLINE idStr &idStr::operator+=( const bool a ) {
|
||
|
Append( a ? "true" : "false" );
|
||
|
return *this;
|
||
|
}
|
||
|
|
||
|
ID_INLINE bool operator==( const idStr &a, const idStr &b ) {
|
||
|
return ( !idStr::Cmp( a.data, b.data ) );
|
||
|
}
|
||
|
|
||
|
ID_INLINE bool operator==( const idStr &a, const char *b ) {
|
||
|
assert( b );
|
||
|
return ( !idStr::Cmp( a.data, b ) );
|
||
|
}
|
||
|
|
||
|
ID_INLINE bool operator==( const char *a, const idStr &b ) {
|
||
|
assert( a );
|
||
|
return ( !idStr::Cmp( a, b.data ) );
|
||
|
}
|
||
|
|
||
|
ID_INLINE bool operator!=( const idStr &a, const idStr &b ) {
|
||
|
return !( a == b );
|
||
|
}
|
||
|
|
||
|
ID_INLINE bool operator!=( const idStr &a, const char *b ) {
|
||
|
return !( a == b );
|
||
|
}
|
||
|
|
||
|
ID_INLINE bool operator!=( const char *a, const idStr &b ) {
|
||
|
return !( a == b );
|
||
|
}
|
||
|
|
||
|
ID_INLINE int idStr::Cmp( const char *text ) const {
|
||
|
assert( text );
|
||
|
return idStr::Cmp( data, text );
|
||
|
}
|
||
|
|
||
|
ID_INLINE int idStr::Cmpn( const char *text, int n ) const {
|
||
|
assert( text );
|
||
|
return idStr::Cmpn( data, text, n );
|
||
|
}
|
||
|
|
||
|
ID_INLINE int idStr::CmpPrefix( const char *text ) const {
|
||
|
assert( text );
|
||
|
return idStr::Cmpn( data, text, strlen( text ) );
|
||
|
}
|
||
|
|
||
|
ID_INLINE int idStr::Icmp( const char *text ) const {
|
||
|
assert( text );
|
||
|
return idStr::Icmp( data, text );
|
||
|
}
|
||
|
|
||
|
ID_INLINE int idStr::Icmpn( const char *text, int n ) const {
|
||
|
assert( text );
|
||
|
return idStr::Icmpn( data, text, n );
|
||
|
}
|
||
|
|
||
|
ID_INLINE int idStr::IcmpPrefix( const char *text ) const {
|
||
|
assert( text );
|
||
|
return idStr::Icmpn( data, text, strlen( text ) );
|
||
|
}
|
||
|
|
||
|
// RAVEN BEGIN
|
||
|
// bdube: escapes
|
||
|
ID_INLINE int idStr::IcmpNoEscape( const char *text ) const {
|
||
|
assert( text );
|
||
|
return idStr::IcmpNoEscape( data, text );
|
||
|
}
|
||
|
// RAVEN END
|
||
|
|
||
|
ID_INLINE int idStr::IcmpPath( const char *text ) const {
|
||
|
assert( text );
|
||
|
return idStr::IcmpPath( data, text );
|
||
|
}
|
||
|
|
||
|
ID_INLINE int idStr::IcmpnPath( const char *text, int n ) const {
|
||
|
assert( text );
|
||
|
return idStr::IcmpnPath( data, text, n );
|
||
|
}
|
||
|
|
||
|
ID_INLINE int idStr::IcmpPrefixPath( const char *text ) const {
|
||
|
assert( text );
|
||
|
return idStr::IcmpnPath( data, text, strlen( text ) );
|
||
|
}
|
||
|
|
||
|
ID_INLINE int idStr::Length( void ) const {
|
||
|
return len;
|
||
|
}
|
||
|
|
||
|
ID_INLINE int idStr::Allocated( void ) const {
|
||
|
if ( data != baseBuffer ) {
|
||
|
return alloced;
|
||
|
} else {
|
||
|
return 0;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
ID_INLINE void idStr::Empty( void ) {
|
||
|
EnsureAlloced( 1 );
|
||
|
data[ 0 ] = '\0';
|
||
|
len = 0;
|
||
|
}
|
||
|
|
||
|
ID_INLINE bool idStr::IsEmpty( void ) const {
|
||
|
return ( idStr::Cmp( data, "" ) == 0 );
|
||
|
}
|
||
|
|
||
|
ID_INLINE void idStr::Clear( void ) {
|
||
|
FreeData();
|
||
|
Init();
|
||
|
}
|
||
|
|
||
|
ID_INLINE void idStr::Append( const char a ) {
|
||
|
EnsureAlloced( len + 2 );
|
||
|
data[ len ] = a;
|
||
|
len++;
|
||
|
data[ len ] = '\0';
|
||
|
}
|
||
|
|
||
|
ID_INLINE void idStr::Append( const idStr &text ) {
|
||
|
int newLen;
|
||
|
int i;
|
||
|
|
||
|
newLen = len + text.Length();
|
||
|
EnsureAlloced( newLen + 1 );
|
||
|
for ( i = 0; i < text.len; i++ ) {
|
||
|
data[ len + i ] = text[ i ];
|
||
|
}
|
||
|
len = newLen;
|
||
|
data[ len ] = '\0';
|
||
|
}
|
||
|
|
||
|
ID_INLINE void idStr::Append( const char *text ) {
|
||
|
int newLen;
|
||
|
int i;
|
||
|
|
||
|
if ( text ) {
|
||
|
newLen = len + strlen( text );
|
||
|
EnsureAlloced( newLen + 1 );
|
||
|
for ( i = 0; text[ i ]; i++ ) {
|
||
|
data[ len + i ] = text[ i ];
|
||
|
}
|
||
|
len = newLen;
|
||
|
data[ len ] = '\0';
|
||
|
}
|
||
|
}
|
||
|
|
||
|
ID_INLINE void idStr::Append( const char *text, int l ) {
|
||
|
int newLen;
|
||
|
int i;
|
||
|
|
||
|
if ( text && l ) {
|
||
|
newLen = len + l;
|
||
|
EnsureAlloced( newLen + 1 );
|
||
|
for ( i = 0; text[ i ] && i < l; i++ ) {
|
||
|
data[ len + i ] = text[ i ];
|
||
|
}
|
||
|
len = newLen;
|
||
|
data[ len ] = '\0';
|
||
|
}
|
||
|
}
|
||
|
|
||
|
ID_INLINE void idStr::Insert( const char a, int index ) {
|
||
|
int i, l;
|
||
|
|
||
|
if ( index < 0 ) {
|
||
|
index = 0;
|
||
|
} else if ( index > len ) {
|
||
|
index = len;
|
||
|
}
|
||
|
|
||
|
l = 1;
|
||
|
EnsureAlloced( len + l + 1 );
|
||
|
for ( i = len; i >= index; i-- ) {
|
||
|
data[i+l] = data[i];
|
||
|
}
|
||
|
data[index] = a;
|
||
|
len++;
|
||
|
}
|
||
|
|
||
|
ID_INLINE void idStr::Insert( const char *text, int index ) {
|
||
|
int i, l;
|
||
|
|
||
|
if ( index < 0 ) {
|
||
|
index = 0;
|
||
|
} else if ( index > len ) {
|
||
|
index = len;
|
||
|
}
|
||
|
|
||
|
l = strlen( text );
|
||
|
EnsureAlloced( len + l + 1 );
|
||
|
for ( i = len; i >= index; i-- ) {
|
||
|
data[i+l] = data[i];
|
||
|
}
|
||
|
for ( i = 0; i < l; i++ ) {
|
||
|
data[index+i] = text[i];
|
||
|
}
|
||
|
len += l;
|
||
|
}
|
||
|
|
||
|
ID_INLINE void idStr::ToLower( void ) {
|
||
|
for (int i = 0; data[i]; i++ ) {
|
||
|
// RAVEN BEGIN
|
||
|
data[i] = ToLower( data[i] );
|
||
|
// RAVEN END
|
||
|
}
|
||
|
}
|
||
|
|
||
|
ID_INLINE void idStr::ToUpper( void ) {
|
||
|
for (int i = 0; data[i]; i++ ) {
|
||
|
// RAVEN BEGIN
|
||
|
data[i] = ToUpper( data[i] );
|
||
|
// RAVEN END
|
||
|
}
|
||
|
}
|
||
|
|
||
|
ID_INLINE bool idStr::IsNumeric( void ) const {
|
||
|
return idStr::IsNumeric( data );
|
||
|
}
|
||
|
|
||
|
ID_INLINE bool idStr::HasLower( void ) const {
|
||
|
return idStr::HasLower( data );
|
||
|
}
|
||
|
|
||
|
ID_INLINE bool idStr::HasUpper( void ) const {
|
||
|
return idStr::HasUpper( data );
|
||
|
}
|
||
|
|
||
|
ID_INLINE int idStr::IsEscape( int* type ) const {
|
||
|
return idStr::IsEscape( data, type );
|
||
|
}
|
||
|
ID_INLINE idStr &idStr::RemoveEscapes ( int escapes ) {
|
||
|
idStr::RemoveEscapes( data, escapes );
|
||
|
len = Length( c_str() );
|
||
|
return *this;
|
||
|
}
|
||
|
ID_INLINE int idStr::LengthWithoutEscapes( void ) const {
|
||
|
return idStr::LengthWithoutEscapes( data );
|
||
|
}
|
||
|
// RAVEN END
|
||
|
|
||
|
ID_INLINE void idStr::CapLength( int newlen ) {
|
||
|
if ( len <= newlen ) {
|
||
|
return;
|
||
|
}
|
||
|
data[ newlen ] = 0;
|
||
|
len = newlen;
|
||
|
}
|
||
|
|
||
|
ID_INLINE void idStr::Fill( const char ch, int newlen ) {
|
||
|
EnsureAlloced( newlen + 1 );
|
||
|
len = newlen;
|
||
|
memset( data, ch, len );
|
||
|
data[ len ] = 0;
|
||
|
}
|
||
|
|
||
|
ID_INLINE int idStr::Find( const char c, int start, int end ) const {
|
||
|
if ( end == -1 ) {
|
||
|
end = len;
|
||
|
}
|
||
|
return idStr::FindChar( data, c, start, end );
|
||
|
}
|
||
|
|
||
|
ID_INLINE int idStr::Find( const char *text, bool casesensitive, int start, int end ) const {
|
||
|
if ( end == -1 ) {
|
||
|
end = len;
|
||
|
}
|
||
|
return idStr::FindText( data, text, casesensitive, start, end );
|
||
|
}
|
||
|
|
||
|
ID_INLINE bool idStr::Filter( const char *filter, bool casesensitive ) const {
|
||
|
return idStr::Filter( filter, data, casesensitive );
|
||
|
}
|
||
|
|
||
|
ID_INLINE const char *idStr::Left( int len, idStr &result ) const {
|
||
|
return Mid( 0, len, result );
|
||
|
}
|
||
|
|
||
|
ID_INLINE const char *idStr::Right( int len, idStr &result ) const {
|
||
|
if ( len >= Length() ) {
|
||
|
result = *this;
|
||
|
return result;
|
||
|
}
|
||
|
return Mid( Length() - len, len, result );
|
||
|
}
|
||
|
|
||
|
ID_INLINE idStr idStr::Left( int len ) const {
|
||
|
return Mid( 0, len );
|
||
|
}
|
||
|
|
||
|
ID_INLINE idStr idStr::Right( int len ) const {
|
||
|
if ( len >= Length() ) {
|
||
|
return *this;
|
||
|
}
|
||
|
return Mid( Length() - len, len );
|
||
|
}
|
||
|
|
||
|
ID_INLINE void idStr::Strip( const char c ) {
|
||
|
StripLeading( c );
|
||
|
StripTrailing( c );
|
||
|
}
|
||
|
|
||
|
ID_INLINE void idStr::Strip( const char *string ) {
|
||
|
StripLeading( string );
|
||
|
StripTrailing( string );
|
||
|
}
|
||
|
|
||
|
ID_INLINE bool idStr::CheckExtension( const char *ext ) {
|
||
|
return idStr::CheckExtension( data, ext );
|
||
|
}
|
||
|
|
||
|
ID_INLINE int idStr::Length( const char *s ) {
|
||
|
int i;
|
||
|
for ( i = 0; s[i]; i++ ) {}
|
||
|
return i;
|
||
|
}
|
||
|
|
||
|
ID_INLINE char *idStr::ToLower( char *s ) {
|
||
|
for ( int i = 0; s[i]; i++ ) {
|
||
|
// RAVEN BEGIN
|
||
|
s[i] = ToLower( s[i] );
|
||
|
// RAVEN END
|
||
|
}
|
||
|
return s;
|
||
|
}
|
||
|
|
||
|
ID_INLINE char *idStr::ToUpper( char *s ) {
|
||
|
for ( int i = 0; s[i]; i++ ) {
|
||
|
// RAVEN BEGIN
|
||
|
s[i] = ToUpper( s[i] );
|
||
|
// RAVEN END
|
||
|
}
|
||
|
return s;
|
||
|
}
|
||
|
|
||
|
ID_INLINE int idStr::Hash( const char *string ) {
|
||
|
int i, hash = 0;
|
||
|
for ( i = 0; *string != '\0'; i++ ) {
|
||
|
hash += ( *string++ ) * ( i + 119 );
|
||
|
}
|
||
|
return hash;
|
||
|
}
|
||
|
|
||
|
ID_INLINE int idStr::Hash( const char *string, int length ) {
|
||
|
int i, hash = 0;
|
||
|
for ( i = 0; i < length; i++ ) {
|
||
|
hash += ( *string++ ) * ( i + 119 );
|
||
|
}
|
||
|
return hash;
|
||
|
}
|
||
|
|
||
|
ID_INLINE int idStr::IHash( const char *string ) {
|
||
|
int i, hash = 0;
|
||
|
for( i = 0; *string != '\0'; i++ ) {
|
||
|
hash += ToLower( *string++ ) * ( i + 119 );
|
||
|
}
|
||
|
return hash;
|
||
|
}
|
||
|
|
||
|
ID_INLINE int idStr::IHash( const char *string, int length ) {
|
||
|
int i, hash = 0;
|
||
|
for ( i = 0; i < length; i++ ) {
|
||
|
hash += ToLower( *string++ ) * ( i + 119 );
|
||
|
}
|
||
|
return hash;
|
||
|
}
|
||
|
|
||
|
ID_INLINE char idStr::ToLower( byte c ) {
|
||
|
// RAVEN BEGIN
|
||
|
if( lowerCaseCharacter[c] ) {
|
||
|
return lowerCaseCharacter[c];
|
||
|
}
|
||
|
// RAVEN END
|
||
|
return c;
|
||
|
}
|
||
|
|
||
|
ID_INLINE char idStr::ToUpper( byte c ) {
|
||
|
// RAVEN BEGIN
|
||
|
if( upperCaseCharacter[c] ) {
|
||
|
return upperCaseCharacter[c];
|
||
|
}
|
||
|
// RAVEN END
|
||
|
return c;
|
||
|
}
|
||
|
|
||
|
ID_INLINE bool idStr::CharIsPrintable( byte c ) {
|
||
|
// RAVEN BEGIN
|
||
|
return printableCharacter[c];
|
||
|
// RAVEN END
|
||
|
}
|
||
|
|
||
|
ID_INLINE bool idStr::CharIsLower( byte c ) {
|
||
|
// RAVEN BEGIN
|
||
|
return !!lowerCaseCharacter[c] && ( lowerCaseCharacter[c] == c );
|
||
|
// RAVEN END
|
||
|
}
|
||
|
|
||
|
ID_INLINE bool idStr::CharIsUpper( byte c ) {
|
||
|
// RAVEN BEGIN
|
||
|
return !!upperCaseCharacter[c] && ( upperCaseCharacter[c] == c );
|
||
|
// RAVEN END
|
||
|
}
|
||
|
|
||
|
ID_INLINE bool idStr::CharIsAlpha( byte c ) {
|
||
|
// test for regular ascii and western European high-ascii chars
|
||
|
return !!upperCaseCharacter[c];
|
||
|
}
|
||
|
|
||
|
ID_INLINE bool idStr::CharIsNumeric( byte c ) {
|
||
|
return ( c <= '9' && c >= '0' );
|
||
|
}
|
||
|
|
||
|
ID_INLINE bool idStr::CharIsNewLine( byte c ) {
|
||
|
return ( c == '\n' || c == '\r' || c == '\v' );
|
||
|
}
|
||
|
|
||
|
ID_INLINE bool idStr::CharIsTab( byte c ) {
|
||
|
return ( c == '\t' );
|
||
|
}
|
||
|
|
||
|
ID_INLINE int idStr::ColorIndex( int c ) {
|
||
|
return ( c & 15 );
|
||
|
}
|
||
|
|
||
|
ID_INLINE int idStr::DynamicMemoryUsed() const {
|
||
|
return ( data == baseBuffer ) ? 0 : alloced;
|
||
|
}
|
||
|
|
||
|
#endif /* !__STR_H__ */
|