2 Copyright (C) 1999-2006 Id Software, Inc. and contributors.
3 For a list of contributors, see the accompanying CONTRIBUTORS file.
5 This file is part of GtkRadiant.
7 GtkRadiant is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 GtkRadiant is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GtkRadiant; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22 //need to rewrite this
24 #ifndef __UTIL_STR_H__
25 #define __UTIL_STR_H__
31 #if GDEF_COMPILER_MSVC
32 #pragma warning(disable : 4710) // function 'blah' not inlined
35 void TestStringClass();
40 strdata () : len( 0 ), refcount( 0 ), data( NULL ), alloced( 0 ) {}
47 void AddRef() { refcount++; }
48 bool DelRef(){ // True if killed
67 void EnsureAlloced( int, bool keepold = true );
68 void EnsureDataWritable();
73 idStr( const char *text );
74 idStr( const idStr& string );
75 idStr( const idStr string, int start, int end );
76 idStr( const char ch );
77 idStr( const int num );
78 idStr( const float num );
79 idStr( const unsigned num );
80 int length( void ) const;
81 int allocated( void ) const;
82 const char * c_str( void ) const;
84 void append( const char *text );
85 void append( const idStr& text );
86 char operator[]( int index ) const;
87 char& operator[]( int index );
89 void operator=( const idStr& text );
90 void operator=( const char *text );
92 friend idStr operator+( const idStr& a, const idStr& b );
93 friend idStr operator+( const idStr& a, const char *b );
94 friend idStr operator+( const char *a, const idStr& b );
96 friend idStr operator+( const idStr& a, const float b );
97 friend idStr operator+( const idStr& a, const int b );
98 friend idStr operator+( const idStr& a, const unsigned b );
99 friend idStr operator+( const idStr& a, const bool b );
100 friend idStr operator+( const idStr& a, const char b );
102 idStr& operator+=( const idStr& a );
103 idStr& operator+=( const char *a );
104 idStr& operator+=( const float a );
105 idStr& operator+=( const char a );
106 idStr& operator+=( const int a );
107 idStr& operator+=( const unsigned a );
108 idStr& operator+=( const bool a );
110 friend bool operator==( const idStr& a, const idStr& b );
111 friend bool operator==( const idStr& a, const char *b );
112 friend bool operator==( const char *a, const idStr& b );
114 friend bool operator!=( const idStr& a, const idStr& b );
115 friend bool operator!=( const idStr& a, const char *b );
116 friend bool operator!=( const char *a, const idStr& b );
118 operator const char *() const;
119 operator const char *();
121 int icmpn( const char *text, int n ) const;
122 int icmpn( const idStr& text, int n ) const;
123 int icmp( const char *text ) const;
124 int icmp( const idStr& text ) const;
125 int cmpn( const char *text, int n ) const;
126 int cmpn( const idStr& text, int n ) const;
127 int cmp( const char *text ) const;
128 int cmp( const idStr& text ) const;
130 void tolower( void );
131 void toupper( void );
133 static char *tolower( char *s1 );
134 static char *toupper( char *s1 );
136 static int icmpn( const char *s1, const char *s2, int n );
137 static int icmp( const char *s1, const char *s2 );
138 static int cmpn( const char *s1, const char *s2, int n );
139 static int cmp( const char *s1, const char *s2 );
141 static void snprintf( char *dst, int size, const char *fmt, ... );
143 static bool isNumeric( const char *str );
144 bool isNumeric( void ) const;
146 void CapLength( int );
148 void BackSlashesToSlashes();
152 inline idStr::~idStr(){
159 inline idStr::idStr() : m_data( NULL ){
161 m_data->data[ 0 ] = 0;
173 len = strlen( text );
174 EnsureAlloced( len + 1 );
175 strcpy( m_data->data, text );
181 m_data->data[ 0 ] = 0;
190 m_data = text.m_data;
203 if ( end > text.length() ) {
207 if ( start > text.length() ) {
208 start = text.length();
216 EnsureAlloced( len + 1 );
218 for ( i = 0; i < len; i++ )
220 m_data->data[ i ] = text[ start + i ];
223 m_data->data[ len ] = 0;
233 m_data->data[ 0 ] = ch;
234 m_data->data[ 1 ] = 0;
245 sprintf( text, "%.3f", num );
246 len = strlen( text );
247 EnsureAlloced( len + 1 );
248 strcpy( m_data->data, text );
259 sprintf( text, "%d", num );
260 len = strlen( text );
261 EnsureAlloced( len + 1 );
262 strcpy( m_data->data, text );
273 sprintf( text, "%u", num );
274 len = strlen( text );
275 EnsureAlloced( len + 1 );
276 strcpy( m_data->data, text );
280 inline int idStr::length( void ) const {
281 return ( m_data != NULL ) ? m_data->len : 0;
284 inline int idStr::allocated( void ) const {
285 return ( m_data != NULL ) ? m_data->alloced + sizeof( *m_data ) : 0;
288 inline const char *idStr::c_str( void ) const {
294 inline void idStr::append
303 len = length() + strlen( text );
304 EnsureAlloced( len + 1 );
306 strcat( m_data->data, text );
311 inline void idStr::append
317 len = length() + text.length();
318 EnsureAlloced( len + 1 );
320 strcat( m_data->data, text.c_str() );
324 inline char idStr::operator[]( int index ) const {
331 // don't include the '/0' in the test, because technically, it's out of bounds
332 assert( ( index >= 0 ) && ( index < m_data->len ) );
334 // In release mode, give them a null character
335 // don't include the '/0' in the test, because technically, it's out of bounds
336 if ( ( index < 0 ) || ( index >= m_data->len ) ) {
340 return m_data->data[ index ];
343 inline char& idStr::operator[]
347 // Used for result for invalid indices
348 static char dummy = 0;
351 // We don't know if they'll write to it or not
352 // if it's not a const object
353 EnsureDataWritable();
359 // don't include the '/0' in the test, because technically, it's out of bounds
360 assert( ( index >= 0 ) && ( index < m_data->len ) );
362 // In release mode, let them change a safe variable
363 // don't include the '/0' in the test, because technically, it's out of bounds
364 if ( ( index < 0 ) || ( index >= m_data->len ) ) {
368 return m_data->data[ index ];
371 inline void idStr::operator=
375 // adding the reference before deleting our current reference prevents
376 // us from deleting our string if we are copying from ourself
377 text.m_data->AddRef();
379 m_data = text.m_data;
382 inline void idStr::operator=
391 // safe behaviour if NULL
392 EnsureAlloced( 1, false );
399 len = strlen( text );
400 EnsureAlloced( len + 1, false );
401 strcpy( m_data->data, text );
406 if ( text == m_data->data ) {
407 return; // Copying same thing. Punt.
410 // If we alias and I don't do this, I could corrupt other strings... This
411 // will get called with EnsureAlloced anyway
412 EnsureDataWritable();
414 // Now we need to check if we're aliasing..
415 if ( text >= m_data->data && text <= m_data->data + m_data->len ) {
416 // Great, we're aliasing. We're copying from inside ourselves.
417 // This means that I don't have to ensure that anything is alloced,
418 // though I'll assert just in case.
419 int diff = text - m_data->data;
422 assert( strlen( text ) < (unsigned) m_data->len );
424 for ( i = 0; text[i]; i++ )
426 m_data->data[i] = text[i];
436 len = strlen( text );
437 EnsureAlloced( len + 1, false );
438 strcpy( m_data->data, text );
442 inline idStr operator+
454 inline idStr operator+
466 inline idStr operator+
478 inline idStr operator+
485 result.append( b ? "true" : "false" );
490 inline idStr operator+
503 inline idStr& idStr::operator+=
511 inline idStr& idStr::operator+=
519 inline idStr& idStr::operator+=
532 inline idStr& idStr::operator+=
536 append( a ? "true" : "false" );
540 inline bool operator==
545 return ( !strcmp( a.c_str(), b.c_str() ) );
548 inline bool operator==
557 return ( !strcmp( a.c_str(), b ) );
560 inline bool operator==
569 return ( !strcmp( a, b.c_str() ) );
572 inline bool operator!=
580 inline bool operator!=
588 inline bool operator!=
596 inline int idStr::icmpn
604 return idStr::icmpn( m_data->data, text, n );
607 inline int idStr::icmpn
613 assert( text.m_data );
615 return idStr::icmpn( m_data->data, text.m_data->data, n );
618 inline int idStr::icmp
625 return idStr::icmp( m_data->data, text );
628 inline int idStr::icmp
633 assert( text.c_str() );
635 return idStr::icmp( c_str(), text.c_str() );
638 inline int idStr::cmp
645 return idStr::cmp( m_data->data, text );
648 inline int idStr::cmp
653 assert( text.c_str() );
655 return idStr::cmp( c_str(), text.c_str() );
658 inline int idStr::cmpn
666 return idStr::cmpn( c_str(), text, n );
669 inline int idStr::cmpn
675 assert( text.c_str() );
677 return idStr::cmpn( c_str(), text.c_str(), n );
680 inline void idStr::tolower
686 EnsureDataWritable();
688 idStr::tolower( m_data->data );
691 inline void idStr::toupper
697 EnsureDataWritable();
699 idStr::toupper( m_data->data );
702 inline bool idStr::isNumeric
707 return idStr::isNumeric( m_data->data );
710 inline idStr::operator const char *() {
714 inline idStr::operator const char *