652 lines
17 KiB
C
652 lines
17 KiB
C
|
// Copyright (C) 2007 Id Software, Inc.
|
||
|
//
|
||
|
|
||
|
#ifndef __WSTR_H__
|
||
|
#define __WSTR_H__
|
||
|
|
||
|
/*
|
||
|
===============================================================================
|
||
|
|
||
|
Wide Character string
|
||
|
|
||
|
===============================================================================
|
||
|
*/
|
||
|
|
||
|
const int W_COLOR_BITS = 31;
|
||
|
|
||
|
// color escape character
|
||
|
const int WC_COLOR_ESCAPE = L'^';
|
||
|
const int WC_COLOR_DEFAULT = L'0';
|
||
|
const int WC_COLOR_RED = L'1';
|
||
|
const int WC_COLOR_GREEN = L'2';
|
||
|
const int WC_COLOR_YELLOW = L'3';
|
||
|
const int WC_COLOR_BLUE = L'4';
|
||
|
const int WC_COLOR_CYAN = L'5';
|
||
|
const int WC_COLOR_MAGENTA = L'6';
|
||
|
const int WC_COLOR_WHITE = L'7';
|
||
|
const int WC_COLOR_GRAY = L'8';
|
||
|
const int WC_COLOR_BLACK = L'9';
|
||
|
const int WC_COLOR_LTGREY = L':';
|
||
|
const int WC_COLOR_MDGREEN = L'<';
|
||
|
const int WC_COLOR_MDYELLOW = L'=';
|
||
|
const int WC_COLOR_MDBLUE = L'>';
|
||
|
const int WC_COLOR_MDRED = L'?';
|
||
|
const int WC_COLOR_LTORANGE = L'A';
|
||
|
const int WC_COLOR_MDCYAN = L'B';
|
||
|
const int WC_COLOR_MDPURPLE = L'C';
|
||
|
const int WC_COLOR_ORANGE = L'D';
|
||
|
|
||
|
// color escape string
|
||
|
#define WS_COLOR_DEFAULT L"^0"
|
||
|
#define WS_COLOR_RED L"^1"
|
||
|
#define WS_COLOR_GREEN L"^2"
|
||
|
#define WS_COLOR_YELLOW L"^3"
|
||
|
#define WS_COLOR_BLUE L"^4"
|
||
|
#define WS_COLOR_CYAN L"^5"
|
||
|
#define WS_COLOR_MAGENTA L"^6"
|
||
|
#define WS_COLOR_WHITE L"^7"
|
||
|
#define WS_COLOR_GRAY L"^8"
|
||
|
#define WS_COLOR_BLACK L"^9"
|
||
|
#define WS_COLOR_LTGREY L"^:"
|
||
|
#define WS_COLOR_MDGREEN L"^<"
|
||
|
#define WS_COLOR_MDYELLOW L"^="
|
||
|
#define WS_COLOR_MDBLUE L"^>"
|
||
|
#define WS_COLOR_MDRED L"^?"
|
||
|
#define WS_COLOR_LTORANGE L"^A"
|
||
|
#define WS_COLOR_MDCYAN L"^B"
|
||
|
#define WS_COLOR_MDPURPLE L"^C"
|
||
|
#define WS_COLOR_ORANGE L"^D"
|
||
|
|
||
|
#ifdef ID_THREAD_SAFE_STR
|
||
|
typedef idDynamicBlockAlloc< wchar_t, 1<<18, 128, true > wideStringDataAllocator_t;
|
||
|
#else
|
||
|
typedef idDynamicBlockAlloc< wchar_t, 1<<18, 128, false > wideStringDataAllocator_t;
|
||
|
#endif
|
||
|
|
||
|
// the size of a wchar over the network
|
||
|
// stick to _WIN32's wchar size (2 bytes)
|
||
|
const int NET_SIZEOF_WCHAR = 2;
|
||
|
|
||
|
class idWStr {
|
||
|
public:
|
||
|
struct hmsFormat_t {
|
||
|
hmsFormat_t() : showZeroMinutes( false ), showZeroHours( false ), showZeroSeconds( true ) {}
|
||
|
bool showZeroMinutes;
|
||
|
bool showZeroHours;
|
||
|
bool showZeroSeconds;
|
||
|
};
|
||
|
|
||
|
idWStr( void );
|
||
|
idWStr( const idWStr& text );
|
||
|
idWStr( const idWStr& text, int start, int end );
|
||
|
idWStr( const wchar_t* text );
|
||
|
idWStr( const wchar_t* text, int start, int end );
|
||
|
~idWStr( void );
|
||
|
|
||
|
size_t Size( void ) const;
|
||
|
const wchar_t* c_str( void ) const;
|
||
|
|
||
|
wchar_t operator[]( int index ) const;
|
||
|
wchar_t & operator[]( int index );
|
||
|
|
||
|
void operator=( const idWStr& text );
|
||
|
void operator=( const wchar_t* text );
|
||
|
|
||
|
friend idWStr operator+( const idStr &a, const idWStr &b );
|
||
|
friend idWStr operator+( const idStr &a, const wchar_t *b );
|
||
|
friend idWStr operator+( const wchar_t *a, const idWStr &b );
|
||
|
|
||
|
idWStr & operator+=( const idWStr &a );
|
||
|
idWStr & operator+=( const wchar_t *a );
|
||
|
idWStr & operator+=( const wchar_t a );
|
||
|
|
||
|
// case sensitive compare
|
||
|
friend bool operator==( const idWStr &a, const idWStr &b );
|
||
|
friend bool operator==( const idWStr &a, const wchar_t *b );
|
||
|
friend bool operator==( const wchar_t *a, const idWStr &b );
|
||
|
|
||
|
// case sensitive compare
|
||
|
friend bool operator!=( const idWStr &a, const idWStr &b );
|
||
|
friend bool operator!=( const idWStr &a, const wchar_t *b );
|
||
|
friend bool operator!=( const wchar_t *a, const idWStr &b );
|
||
|
|
||
|
// case sensitive compare
|
||
|
int Cmp( const wchar_t *text ) const;
|
||
|
int Cmpn( const wchar_t *text, int n ) const;
|
||
|
int CmpPrefix( const wchar_t *text ) const;
|
||
|
|
||
|
// case insensitive compare
|
||
|
int Icmp( const wchar_t *text ) const;
|
||
|
int Icmpn( const wchar_t *text, int n ) const;
|
||
|
int IcmpPrefix( const wchar_t *text ) const;
|
||
|
|
||
|
// case insensitive compare ignoring color
|
||
|
int IcmpNoColor( const wchar_t *text ) const;
|
||
|
|
||
|
int Length( void ) const;
|
||
|
int Allocated( void ) const;
|
||
|
void Empty( void );
|
||
|
bool IsEmpty( void ) const;
|
||
|
void Clear( void );
|
||
|
void Append( const wchar_t a );
|
||
|
void Append( const idWStr &text );
|
||
|
void Append( const wchar_t *text );
|
||
|
void Append( const wchar_t *text, int len );
|
||
|
void Append( int count, const wchar_t c );
|
||
|
void Insert( const wchar_t a, int index );
|
||
|
void Insert( const wchar_t *text, int index );
|
||
|
bool IsColor( void ) const;
|
||
|
int LengthWithoutColors( void ) const;
|
||
|
idWStr & RemoveColors( void );
|
||
|
void CapLength( int );
|
||
|
void Fill( const wchar_t ch, int newlen );
|
||
|
void Swap( idWStr& rhs );
|
||
|
idWStr& CollapseColors( void );
|
||
|
|
||
|
int Find( const wchar_t c, int start = 0, int end = INVALID_POSITION ) const;
|
||
|
int Find( const wchar_t *text, bool casesensitive = true, int start = 0, int end = INVALID_POSITION ) const;
|
||
|
const wchar_t * Mid( int start, int len, idWStr &result ) const; // store 'len' characters starting at 'start' in result
|
||
|
idWStr Mid( int start, int len ) const; // return 'len' characters starting at 'start'
|
||
|
void Strip( const char *string ); // strip string from front and end as many times as the string occurs
|
||
|
void Replace( const wchar_t *old, const wchar_t *nw );
|
||
|
void ReplaceFirst( const wchar_t *old, const wchar_t *nw );
|
||
|
void ReplaceChar( wchar_t oldChar, wchar_t newChar );
|
||
|
void EraseRange( int start, int len = INVALID_POSITION );
|
||
|
void EraseChar( const wchar_t c, int start = 0 );
|
||
|
|
||
|
idWStr& StripFileExtension();
|
||
|
|
||
|
// char * methods to replace library functions
|
||
|
static int Length( const wchar_t* s );
|
||
|
static bool IsColor( const wchar_t *s );
|
||
|
static int LengthWithoutColors( const wchar_t *s );
|
||
|
static wchar_t * RemoveColors( wchar_t *s );
|
||
|
static wchar_t * StripFilename( wchar_t *s );
|
||
|
static int Cmp( const wchar_t *s1, const wchar_t *s2 );
|
||
|
static int Cmpn( const wchar_t *s1, const wchar_t *s2, int n );
|
||
|
static int Icmp( const wchar_t *s1, const wchar_t *s2 );
|
||
|
static int Icmpn( const wchar_t *s1, const wchar_t *s2, int n );
|
||
|
static int IcmpNoColor( const wchar_t *s1, const wchar_t *s2 );
|
||
|
static void Append( wchar_t *dest, int size, const wchar_t *src );
|
||
|
static void Copynz( wchar_t *dest, const wchar_t *src, int destsize );
|
||
|
static int snPrintf( wchar_t *dest, int size, const wchar_t *fmt, ... );
|
||
|
static int vsnPrintf( wchar_t *dest, int size, const wchar_t *fmt, va_list argptr );
|
||
|
static int FindChar( const wchar_t *str, const wchar_t c, int start = 0, int end = INVALID_POSITION );
|
||
|
static int FindText( const wchar_t *str, const wchar_t *text, bool casesensitive = true, int start = 0, int end = INVALID_POSITION );
|
||
|
|
||
|
static const wchar_t* MS2HMS( double ms, const hmsFormat_t& formatSpec = defaultHMSFormat );
|
||
|
|
||
|
// 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 int ColorIndex( wchar_t c );
|
||
|
static const idVec4&ColorForIndex( int i );
|
||
|
static const idVec4&ColorForChar( wchar_t c );
|
||
|
static const char* StrForColorIndex( int i );
|
||
|
static dword& DColorForIndex( int i );
|
||
|
static dword& DColorForChar( wchar_t c );
|
||
|
|
||
|
friend int swprintf( idWStr &dest, const wchar_t *fmt, ... );
|
||
|
friend int vswprintf( idWStr &dest, const wchar_t *fmt, va_list ap );
|
||
|
|
||
|
void ReAllocate( int amount, bool keepold ); // reallocate string data buffer
|
||
|
void FreeData( void ); // free allocated string memory
|
||
|
|
||
|
static void InitMemory( void );
|
||
|
static void ShutdownMemory( void );
|
||
|
static void PurgeMemory( void );
|
||
|
static void ShowMemoryUsage_f( const idCmdArgs &args );
|
||
|
|
||
|
static void SetStringAllocator( wideStringDataAllocator_t* allocator );
|
||
|
static wideStringDataAllocator_t* GetStringAllocator( void );
|
||
|
|
||
|
static void Test( void );
|
||
|
|
||
|
protected:
|
||
|
int len;
|
||
|
wchar_t * data;
|
||
|
int alloced;
|
||
|
wchar_t 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 enough
|
||
|
|
||
|
static wideStringDataAllocator_t* stringDataAllocator;
|
||
|
static bool stringAllocatorIsShared;
|
||
|
static hmsFormat_t defaultHMSFormat;
|
||
|
|
||
|
public:
|
||
|
static const int INVALID_POSITION = -1;
|
||
|
};
|
||
|
|
||
|
/*
|
||
|
============
|
||
|
va utility funcs
|
||
|
============
|
||
|
*/
|
||
|
|
||
|
wchar_t* va( const wchar_t *fmt, ... );
|
||
|
|
||
|
|
||
|
ID_INLINE void idWStr::EnsureAlloced( int amount, bool keepold ) {
|
||
|
if ( amount > alloced ) {
|
||
|
ReAllocate( amount, keepold );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
ID_INLINE void idWStr::Init( void ) {
|
||
|
len = 0;
|
||
|
alloced = STR_ALLOC_BASE;
|
||
|
data = baseBuffer;
|
||
|
data[ 0 ] = L'\0';
|
||
|
#ifdef ID_DEBUG_UNINITIALIZED_MEMORY
|
||
|
::wmemset( baseBuffer, 0, sizeof( baseBuffer ) );
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
ID_INLINE idWStr::idWStr( void ) {
|
||
|
Init();
|
||
|
}
|
||
|
|
||
|
ID_INLINE idWStr::idWStr( const idWStr &text ) {
|
||
|
int l;
|
||
|
|
||
|
Init();
|
||
|
l = text.Length();
|
||
|
EnsureAlloced( l + 1 );
|
||
|
wcscpy( data, text.data );
|
||
|
len = l;
|
||
|
}
|
||
|
|
||
|
ID_INLINE idWStr::idWStr( const idWStr &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 idWStr::idWStr( const wchar_t *text ) {
|
||
|
int l;
|
||
|
|
||
|
Init();
|
||
|
if ( text ) {
|
||
|
l = Length( text );
|
||
|
EnsureAlloced( l + 1 );
|
||
|
wcscpy( data, text );
|
||
|
len = l;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
ID_INLINE idWStr::idWStr( const wchar_t *text, int start, int end ) {
|
||
|
int i;
|
||
|
int l = Length( 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 idWStr::~idWStr( void ) {
|
||
|
Clear();
|
||
|
}
|
||
|
|
||
|
ID_INLINE size_t idWStr::Size( void ) const {
|
||
|
return sizeof( *this ) + Allocated() * sizeof( wchar_t );
|
||
|
}
|
||
|
|
||
|
ID_INLINE const wchar_t *idWStr::c_str( void ) const {
|
||
|
return data;
|
||
|
}
|
||
|
|
||
|
ID_INLINE wchar_t idWStr::operator[]( int index ) const {
|
||
|
assert( ( index >= 0 ) && ( index <= len ) );
|
||
|
return data[ index ];
|
||
|
}
|
||
|
|
||
|
ID_INLINE wchar_t &idWStr::operator[]( int index ) {
|
||
|
assert( ( index >= 0 ) && ( index <= len ) );
|
||
|
return data[ index ];
|
||
|
}
|
||
|
|
||
|
ID_INLINE void idWStr::operator=( const idWStr &text ) {
|
||
|
int l;
|
||
|
|
||
|
l = text.Length();
|
||
|
EnsureAlloced( l + 1, false );
|
||
|
::wmemcpy( data, text.data, l );
|
||
|
data[l] = L'\0';
|
||
|
len = l;
|
||
|
}
|
||
|
|
||
|
ID_INLINE idWStr operator+( const idWStr &a, const idWStr &b ) {
|
||
|
idWStr result( a );
|
||
|
result.Append( b );
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
ID_INLINE idWStr operator+( const idWStr &a, const wchar_t *b ) {
|
||
|
idWStr result( a );
|
||
|
result.Append( b );
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
ID_INLINE idWStr operator+( const wchar_t *a, const idWStr &b ) {
|
||
|
idWStr result( a );
|
||
|
result.Append( b );
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
ID_INLINE idWStr operator+( const idWStr &a, const wchar_t b ) {
|
||
|
idWStr result( a );
|
||
|
result.Append( b );
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
ID_INLINE idWStr &idWStr::operator+=( const idWStr &a ) {
|
||
|
Append( a );
|
||
|
return *this;
|
||
|
}
|
||
|
|
||
|
ID_INLINE idWStr &idWStr::operator+=( const wchar_t *a ) {
|
||
|
Append( a );
|
||
|
return *this;
|
||
|
}
|
||
|
|
||
|
ID_INLINE idWStr &idWStr::operator+=( const wchar_t a ) {
|
||
|
Append( a );
|
||
|
return *this;
|
||
|
}
|
||
|
|
||
|
ID_INLINE bool operator==( const idWStr &a, const idWStr &b ) {
|
||
|
return ( !idWStr::Cmp( a.data, b.data ) );
|
||
|
}
|
||
|
|
||
|
ID_INLINE bool operator==( const idWStr &a, const wchar_t *b ) {
|
||
|
assert( b );
|
||
|
return ( !idWStr::Cmp( a.data, b ) );
|
||
|
}
|
||
|
|
||
|
ID_INLINE bool operator==( const wchar_t *a, const idWStr &b ) {
|
||
|
assert( a );
|
||
|
return ( !idWStr::Cmp( a, b.data ) );
|
||
|
}
|
||
|
|
||
|
ID_INLINE bool operator!=( const idWStr &a, const idWStr &b ) {
|
||
|
return !( a == b );
|
||
|
}
|
||
|
|
||
|
ID_INLINE bool operator!=( const idWStr &a, const wchar_t *b ) {
|
||
|
return !( a == b );
|
||
|
}
|
||
|
|
||
|
ID_INLINE bool operator!=( const wchar_t *a, const idWStr &b ) {
|
||
|
return !( a == b );
|
||
|
}
|
||
|
|
||
|
ID_INLINE int idWStr::Cmp( const wchar_t *text ) const {
|
||
|
assert( text );
|
||
|
return idWStr::Cmp( data, text );
|
||
|
}
|
||
|
|
||
|
ID_INLINE int idWStr::Cmpn( const wchar_t *text, int n ) const {
|
||
|
assert( text );
|
||
|
return idWStr::Cmpn( data, text, n );
|
||
|
}
|
||
|
|
||
|
ID_INLINE int idWStr::CmpPrefix( const wchar_t *text ) const {
|
||
|
assert( text );
|
||
|
return Cmpn( data, text, Length( text ) );
|
||
|
}
|
||
|
|
||
|
ID_INLINE int idWStr::Icmp( const wchar_t *text ) const {
|
||
|
assert( text );
|
||
|
return Icmp( data, text );
|
||
|
}
|
||
|
|
||
|
ID_INLINE int idWStr::Icmpn( const wchar_t *text, int n ) const {
|
||
|
assert( text );
|
||
|
return Icmpn( data, text, n );
|
||
|
}
|
||
|
|
||
|
ID_INLINE int idWStr::IcmpPrefix( const wchar_t *text ) const {
|
||
|
assert( text );
|
||
|
return Icmpn( data, text, Length( text ) );
|
||
|
}
|
||
|
|
||
|
ID_INLINE int idWStr::IcmpNoColor( const wchar_t *text ) const {
|
||
|
assert( text );
|
||
|
return IcmpNoColor( data, text );
|
||
|
}
|
||
|
|
||
|
ID_INLINE int idWStr::Length( void ) const {
|
||
|
return len;
|
||
|
}
|
||
|
|
||
|
ID_INLINE int idWStr::Allocated( void ) const {
|
||
|
if ( data != baseBuffer ) {
|
||
|
return alloced;
|
||
|
} else {
|
||
|
return 0;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
ID_INLINE void idWStr::Empty( void ) {
|
||
|
EnsureAlloced( 1 );
|
||
|
data[ 0 ] = L'\0';
|
||
|
len = 0;
|
||
|
}
|
||
|
|
||
|
ID_INLINE bool idWStr::IsEmpty( void ) const {
|
||
|
return ( Cmp( data, L"" ) == 0 );
|
||
|
}
|
||
|
|
||
|
ID_INLINE void idWStr::Clear( void ) {
|
||
|
FreeData();
|
||
|
Init();
|
||
|
}
|
||
|
|
||
|
ID_INLINE void idWStr::Append( const wchar_t a ) {
|
||
|
EnsureAlloced( len + 2 );
|
||
|
data[ len ] = a;
|
||
|
len++;
|
||
|
data[ len ] = L'\0';
|
||
|
}
|
||
|
|
||
|
ID_INLINE void idWStr::Append( const idWStr &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 ] = L'\0';
|
||
|
}
|
||
|
|
||
|
ID_INLINE void idWStr::Append( const wchar_t *text ) {
|
||
|
int newLen;
|
||
|
int i;
|
||
|
|
||
|
if ( text ) {
|
||
|
newLen = len + Length( text );
|
||
|
EnsureAlloced( newLen + 1 );
|
||
|
for ( i = 0; text[ i ]; i++ ) {
|
||
|
data[ len + i ] = text[ i ];
|
||
|
}
|
||
|
len = newLen;
|
||
|
data[ len ] = L'\0';
|
||
|
}
|
||
|
}
|
||
|
|
||
|
ID_INLINE void idWStr::Append( const wchar_t *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 ] = L'\0';
|
||
|
}
|
||
|
}
|
||
|
|
||
|
ID_INLINE void idWStr::Insert( const wchar_t 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 idWStr::Insert( const wchar_t *text, int index ) {
|
||
|
int i, l;
|
||
|
|
||
|
if ( index < 0 ) {
|
||
|
index = 0;
|
||
|
} else if ( index > len ) {
|
||
|
index = len;
|
||
|
}
|
||
|
|
||
|
l = Length( 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 bool idWStr::IsColor( void ) const {
|
||
|
return IsColor( data );
|
||
|
}
|
||
|
|
||
|
ID_INLINE idWStr &idWStr::RemoveColors( void ) {
|
||
|
RemoveColors( data );
|
||
|
len = Length( data );
|
||
|
return *this;
|
||
|
}
|
||
|
|
||
|
ID_INLINE int idWStr::LengthWithoutColors( void ) const {
|
||
|
return LengthWithoutColors( data );
|
||
|
}
|
||
|
|
||
|
ID_INLINE void idWStr::CapLength( int newlen ) {
|
||
|
if ( len <= newlen ) {
|
||
|
return;
|
||
|
}
|
||
|
data[ newlen ] = L'\0';
|
||
|
len = newlen;
|
||
|
}
|
||
|
|
||
|
ID_INLINE void idWStr::Fill( const wchar_t ch, int newlen ) {
|
||
|
EnsureAlloced( newlen + 1 );
|
||
|
len = newlen;
|
||
|
::wmemset( data, ch, len );
|
||
|
data[ len ] = L'\0';
|
||
|
}
|
||
|
|
||
|
ID_INLINE int idWStr::Find( const wchar_t c, int start, int end ) const {
|
||
|
if ( end == INVALID_POSITION ) {
|
||
|
end = len;
|
||
|
}
|
||
|
return FindChar( data, c, start, end );
|
||
|
}
|
||
|
|
||
|
ID_INLINE int idWStr::Find( const wchar_t *text, bool casesensitive, int start, int end ) const {
|
||
|
if ( end == INVALID_POSITION ) {
|
||
|
end = len;
|
||
|
}
|
||
|
return FindText( data, text, casesensitive, start, end );
|
||
|
}
|
||
|
|
||
|
ID_INLINE int idWStr::Length( const wchar_t *s ) {
|
||
|
int i;
|
||
|
for ( i = 0; s[i] != L'\0'; i++ ) {}
|
||
|
return i;
|
||
|
}
|
||
|
|
||
|
ID_INLINE bool idWStr::IsColor( const wchar_t *s ) {
|
||
|
return ( s && s[0] == WC_COLOR_ESCAPE && s[1] != L'\0' && s[1] != L' ' );
|
||
|
}
|
||
|
|
||
|
ID_INLINE int idWStr::ColorIndex( wchar_t c ) {
|
||
|
return ( ( c - L'0' ) & W_COLOR_BITS );
|
||
|
}
|
||
|
|
||
|
ID_INLINE void idWStr::Swap( idWStr& rhs ) {
|
||
|
if( rhs.data != rhs.baseBuffer && data != baseBuffer ) {
|
||
|
idSwap( data, rhs.data );
|
||
|
idSwap( len, rhs.len);
|
||
|
idSwap( alloced, rhs.alloced );
|
||
|
} else {
|
||
|
idSwap( *this, rhs );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#endif /* !__WSTR_H__ */
|
||
|
|