2 Copyright (c) 2001, Loki software, inc.
5 Redistribution and use in source and binary forms, with or without modification,
6 are permitted provided that the following conditions are met:
8 Redistributions of source code must retain the above copyright notice, this list
9 of conditions and the following disclaimer.
11 Redistributions in binary form must reproduce the above copyright notice, this
12 list of conditions and the following disclaimer in the documentation and/or
13 other materials provided with the distribution.
15 Neither the name of Loki software nor the names of its contributors may be used
16 to endorse or promote products derived from this software without specific prior
19 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
20 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22 DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
23 DIRECT,INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
26 ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 // loose replacement for CString from MFC
52 #define strcasecmp strcmpi
55 // NOTE TTimo __StrDup was initially implemented in pakstuff.cpp
56 // causing a bunch of issues for broader targets that use Str.h (such as plugins and modules)
57 // Q_StrDup should be used now, using a #define __StrDup for easy transition
59 #define __StrDup Q_StrDup
61 inline char* Q_StrDup( char* _pStr ) {
62 const char* pStr = _pStr;
67 return strcpy( new char[ strlen( pStr ) + 1 ], pStr );
70 inline char* Q_StrDup( const char* pStr ) {
75 return strcpy( new char[strlen( pStr ) + 1], pStr );
78 #if defined ( __linux__ ) || defined ( __APPLE__ )
79 #define strcmpi strcasecmp
80 #define stricmp strcasecmp
81 #define strnicmp strncasecmp
83 inline char* strlwr( char* string ){
85 for ( cp = string; *cp; ++cp )
87 if ( 'A' <= *cp && *cp <= 'Z' ) {
95 inline char* strupr( char* string ){
97 for ( cp = string; *cp; ++cp )
99 if ( 'a' <= *cp && *cp <= 'z' ) {
108 static char *g_pStrWork = NULL;
118 m_bIgnoreCase = true;
119 m_pStr = new char[1];
124 m_bIgnoreCase = true;
125 m_pStr = __StrDup( p );
128 Str( const char *p ){
129 m_bIgnoreCase = true;
130 m_pStr = __StrDup( p );
133 Str( const unsigned char *p ){
134 m_bIgnoreCase = true;
135 m_pStr = __StrDup( (const char *)p );
139 m_bIgnoreCase = true;
140 m_pStr = new char[2];
145 const char* GetBuffer() const {
150 m_bIgnoreCase = true;
151 m_pStr = __StrDup( s.GetBuffer() );
159 void Allocate( int n ){
161 m_pStr = new char[n];
166 m_pStr = __StrDup( "" );
171 // NOTE TTimo: someone explain this g_pStrWork to me?
192 char* lpszLast = NULL;
193 while ( *lpsz != '\0' )
195 if ( isspace( *lpsz ) ) {
196 if ( lpszLast == NULL ) {
206 if ( lpszLast != NULL ) {
207 // truncate at trailing space start
213 // find first non-space character
215 while ( isspace( *lpsz ) )
218 // fix up data and length
219 int nDataLength = GetLength() - ( lpsz - m_pStr );
220 memmove( m_pStr, lpsz, ( nDataLength + 1 ) );
223 int Find( const char *p ){
224 char *pf = strstr( m_pStr, p );
225 return ( pf ) ? ( pf - m_pStr ) : -1;
228 // search starting at a given offset
229 int Find( const char *p, int offset ){
230 char *pf = strstr( m_pStr + offset, p );
231 return ( pf ) ? ( pf - m_pStr ) : -1;
234 int Find( const char ch ){
235 char *pf = strchr( m_pStr, ch );
236 return ( pf ) ? ( pf - m_pStr ) : -1;
239 int ReverseFind( const char ch ){
240 char *pf = strrchr( m_pStr, ch );
241 return ( pf ) ? ( pf - m_pStr ) : -1;
244 int Compare( const char* str ) const {
245 return strcmp( m_pStr, str );
248 int CompareNoCase( const char* str ) const {
249 return strcasecmp( m_pStr, str );
253 return ( m_pStr ) ? strlen( m_pStr ) : 0;
256 const char* Left( int n ){
259 g_pStrWork = new char[n + 1];
260 strncpy( g_pStrWork, m_pStr, n );
261 g_pStrWork[n] = '\0';
265 g_pStrWork = new char[1];
266 g_pStrWork[0] = '\0';
271 const char* Right( int n ){
274 g_pStrWork = new char[n + 1];
275 int nStart = GetLength() - n;
276 strncpy( g_pStrWork, &m_pStr[nStart], n );
277 g_pStrWork[n] = '\0';
281 g_pStrWork = new char[1];
282 g_pStrWork[0] = '\0';
287 const char* Mid( int nFirst ) const {
288 return Mid( nFirst, strlen( m_pStr ) - nFirst );
291 const char* Mid( int first, int n ) const {
294 g_pStrWork = new char[n + 1];
295 strncpy( g_pStrWork, m_pStr + first, n );
296 g_pStrWork[n] = '\0';
300 g_pStrWork = new char[1];
301 g_pStrWork[0] = '\0';
307 void Format( const char* fmt, ... ){
311 va_start( args, fmt );
312 buffer = g_strdup_vprintf( fmt, args );
316 m_pStr = __StrDup( buffer );
320 void Format( const char* fmt, ... ){
322 m_pStr = new char[1024];
324 va_start( args, fmt );
325 vsprintf( m_pStr, fmt, args );
330 void SetAt( int n, char ch ){
331 if ( n >= 0 && n < GetLength() ) {
336 // NOTE: unlike CString, this looses the pointer
337 void ReleaseBuffer( int n = -1 ){
344 m_pStr = __StrDup( tmp );
348 char* GetBufferSetLength( int n ){
353 char *p = new char[n + 1];
354 strncpy( p, m_pStr, n );
361 // char& operator *() { return *m_pStr; }
362 // char& operator *() const { return *const_cast<Str*>(this)->m_pStr; }
369 operator const char*(){
370 return reinterpret_cast<const char*>( m_pStr );
372 operator unsigned char*() {
373 return reinterpret_cast<unsigned char*>( m_pStr );
375 operator const unsigned char*() {
376 return reinterpret_cast<const unsigned char*>( m_pStr );
378 Str& operator =( const Str& rhs ){
379 if ( &rhs != this ) {
381 m_pStr = __StrDup( rhs.m_pStr );
386 Str& operator =( const char* pStr ){
387 if ( m_pStr != pStr ) {
389 m_pStr = __StrDup( pStr );
394 Str& operator +=( const char ch ){
395 int len = GetLength();
396 char *p = new char[len + 1 + 1];
405 m_pStr[len + 1] = '\0';
410 Str& operator +=( const char *pStr ){
413 char *p = new char[strlen( m_pStr ) + strlen( pStr ) + 1];
421 m_pStr = __StrDup( pStr );
428 bool operator ==( const Str& rhs ) const { return ( m_bIgnoreCase ) ? stricmp( m_pStr, rhs.m_pStr ) == 0 : strcmp( m_pStr, rhs.m_pStr ) == 0; }
429 bool operator ==( char* pStr ) const { return ( m_bIgnoreCase ) ? stricmp( m_pStr, pStr ) == 0 : strcmp( m_pStr, pStr ) == 0; }
430 bool operator ==( const char* pStr ) const { return ( m_bIgnoreCase ) ? stricmp( m_pStr, pStr ) == 0 : strcmp( m_pStr, pStr ) == 0; }
431 bool operator !=( Str& rhs ) const { return ( m_bIgnoreCase ) ? stricmp( m_pStr, rhs.m_pStr ) != 0 : strcmp( m_pStr, rhs.m_pStr ) != 0; }
432 bool operator !=( char* pStr ) const { return ( m_bIgnoreCase ) ? stricmp( m_pStr, pStr ) != 0 : strcmp( m_pStr, pStr ) != 0; }
433 bool operator !=( const char* pStr ) const { return ( m_bIgnoreCase ) ? stricmp( m_pStr, pStr ) != 0 : strcmp( m_pStr, pStr ) != 0; }
434 bool operator <( const Str& rhs ) const { return ( m_bIgnoreCase ) ? stricmp( m_pStr, rhs.m_pStr ) < 0 : strcmp( m_pStr, rhs.m_pStr ) < 0; }
435 bool operator <( char* pStr ) const { return ( m_bIgnoreCase ) ? stricmp( m_pStr, pStr ) < 0 : strcmp( m_pStr, pStr ) < 0; }
436 bool operator <( const char* pStr ) const { return ( m_bIgnoreCase ) ? stricmp( m_pStr, pStr ) < 0 : strcmp( m_pStr, pStr ) < 0; }
437 bool operator >( const Str& rhs ) const { return ( m_bIgnoreCase ) ? stricmp( m_pStr, rhs.m_pStr ) > 0 : strcmp( m_pStr, rhs.m_pStr ) > 0; }
438 bool operator >( char* pStr ) const { return ( m_bIgnoreCase ) ? stricmp( m_pStr, pStr ) > 0 : strcmp( m_pStr, pStr ) > 0; }
439 bool operator >( const char* pStr ) const { return ( m_bIgnoreCase ) ? stricmp( m_pStr, pStr ) > 0 : strcmp( m_pStr, pStr ) > 0; }
440 char& operator []( int nIndex ) { return m_pStr[nIndex]; }
441 char& operator []( int nIndex ) const { return m_pStr[nIndex]; }
442 const char GetAt( int nIndex ) { return m_pStr[nIndex]; }