2 Copyright (C) 1999-2007 id Software, Inc. and contributors.
\r
3 For a list of contributors, see the accompanying CONTRIBUTORS file.
\r
5 This file is part of GtkRadiant.
\r
7 GtkRadiant is free software; you can redistribute it and/or modify
\r
8 it under the terms of the GNU General Public License as published by
\r
9 the Free Software Foundation; either version 2 of the License, or
\r
10 (at your option) any later version.
\r
12 GtkRadiant is distributed in the hope that it will be useful,
\r
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
\r
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
\r
15 GNU General Public License for more details.
\r
17 You should have received a copy of the GNU General Public License
\r
18 along with GtkRadiant; if not, write to the Free Software
\r
19 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
\r
22 //need to rewrite this
\r
24 #ifndef __UTIL_STR_H__
\r
25 #define __UTIL_STR_H__
\r
32 #pragma warning(disable : 4710) // function 'blah' not inlined
\r
35 void TestStringClass ();
\r
40 strdata () : len( 0 ), refcount ( 0 ), data ( NULL ), alloced ( 0 ) {}
\r
47 void AddRef () { refcount++; }
\r
48 bool DelRef () // True if killed
\r
69 void EnsureAlloced ( int, bool keepold = true );
\r
70 void EnsureDataWritable ();
\r
75 idStr( const char *text );
\r
76 idStr( const idStr& string );
\r
77 idStr( const idStr string, int start, int end );
\r
78 idStr( const char ch );
\r
79 idStr( const int num );
\r
80 idStr( const float num );
\r
81 idStr( const unsigned num );
\r
82 int length( void ) const;
\r
83 int allocated( void ) const;
\r
84 const char * c_str( void ) const;
\r
86 void append( const char *text );
\r
87 void append( const idStr& text );
\r
88 char operator[]( int index ) const;
\r
89 char& operator[]( int index );
\r
91 void operator=( const idStr& text );
\r
92 void operator=( const char *text );
\r
94 friend idStr operator+( const idStr& a, const idStr& b );
\r
95 friend idStr operator+( const idStr& a, const char *b );
\r
96 friend idStr operator+( const char *a, const idStr& b );
\r
98 friend idStr operator+( const idStr& a, const float b );
\r
99 friend idStr operator+( const idStr& a, const int b );
\r
100 friend idStr operator+( const idStr& a, const unsigned b );
\r
101 friend idStr operator+( const idStr& a, const bool b );
\r
102 friend idStr operator+( const idStr& a, const char b );
\r
104 idStr& operator+=( const idStr& a );
\r
105 idStr& operator+=( const char *a );
\r
106 idStr& operator+=( const float a );
\r
107 idStr& operator+=( const char a );
\r
108 idStr& operator+=( const int a );
\r
109 idStr& operator+=( const unsigned a );
\r
110 idStr& operator+=( const bool a );
\r
112 friend bool operator==( const idStr& a, const idStr& b );
\r
113 friend bool operator==( const idStr& a, const char *b );
\r
114 friend bool operator==( const char *a, const idStr& b );
\r
116 friend bool operator!=( const idStr& a, const idStr& b );
\r
117 friend bool operator!=( const idStr& a, const char *b );
\r
118 friend bool operator!=( const char *a, const idStr& b );
\r
120 operator const char * () const;
\r
121 operator const char * ();
\r
123 int icmpn( const char *text, int n ) const;
\r
124 int icmpn( const idStr& text, int n ) const;
\r
125 int icmp( const char *text ) const;
\r
126 int icmp( const idStr& text ) const;
\r
127 int cmpn( const char *text, int n ) const;
\r
128 int cmpn( const idStr& text, int n ) const;
\r
129 int cmp( const char *text ) const;
\r
130 int cmp( const idStr& text ) const;
\r
132 void tolower( void );
\r
133 void toupper( void );
\r
135 static char *tolower( char *s1 );
\r
136 static char *toupper( char *s1 );
\r
138 static int icmpn( const char *s1, const char *s2, int n );
\r
139 static int icmp( const char *s1, const char *s2 );
\r
140 static int cmpn( const char *s1, const char *s2, int n );
\r
141 static int cmp( const char *s1, const char *s2 );
\r
143 static void snprintf ( char *dst, int size, const char *fmt, ... );
\r
145 static bool isNumeric( const char *str );
\r
146 bool isNumeric( void ) const;
\r
148 void CapLength ( int );
\r
150 void BackSlashesToSlashes ();
\r
154 inline idStr::~idStr()
\r
163 inline idStr::idStr() : m_data ( NULL )
\r
165 EnsureAlloced ( 1 );
\r
166 m_data->data[ 0 ] = 0;
\r
169 inline idStr::idStr
\r
172 ) : m_data ( NULL )
\r
181 len = strlen( text );
\r
182 EnsureAlloced ( len + 1 );
\r
183 strcpy( m_data->data, text );
\r
188 EnsureAlloced ( 1 );
\r
189 m_data->data[ 0 ] = 0;
\r
194 inline idStr::idStr
\r
197 ) : m_data ( NULL )
\r
200 m_data = text.m_data;
\r
204 inline idStr::idStr
\r
209 ) : m_data ( NULL )
\r
215 if ( end > text.length() )
\r
217 end = text.length();
\r
220 if ( start > text.length() )
\r
222 start = text.length();
\r
231 EnsureAlloced ( len + 1 );
\r
233 for( i = 0; i < len; i++ )
\r
235 m_data->data[ i ] = text[ start + i ];
\r
238 m_data->data[ len ] = 0;
\r
242 inline idStr::idStr
\r
245 ) : m_data ( NULL )
\r
248 EnsureAlloced ( 2 );
\r
250 m_data->data[ 0 ] = ch;
\r
251 m_data->data[ 1 ] = 0;
\r
255 inline idStr::idStr
\r
258 ) : m_data ( NULL )
\r
264 sprintf( text, "%.3f", num );
\r
265 len = strlen( text );
\r
266 EnsureAlloced( len + 1 );
\r
267 strcpy( m_data->data, text );
\r
271 inline idStr::idStr
\r
274 ) : m_data ( NULL )
\r
280 sprintf( text, "%d", num );
\r
281 len = strlen( text );
\r
282 EnsureAlloced( len + 1 );
\r
283 strcpy( m_data->data, text );
\r
287 inline idStr::idStr
\r
290 ) : m_data ( NULL )
\r
296 sprintf( text, "%u", num );
\r
297 len = strlen( text );
\r
298 EnsureAlloced( len + 1 );
\r
299 strcpy( m_data->data, text );
\r
303 inline int idStr::length( void ) const
\r
305 return ( m_data != NULL ) ? m_data->len : 0;
\r
308 inline int idStr::allocated( void ) const
\r
310 return ( m_data != NULL ) ? m_data->alloced + sizeof( *m_data ) : 0;
\r
313 inline const char *idStr::c_str( void ) const
\r
317 return m_data->data;
\r
320 inline void idStr::append
\r
332 len = length() + strlen( text );
\r
333 EnsureAlloced( len + 1 );
\r
335 strcat( m_data->data, text );
\r
340 inline void idStr::append
\r
348 len = length() + text.length();
\r
349 EnsureAlloced ( len + 1 );
\r
351 strcat ( m_data->data, text.c_str () );
\r
355 inline char idStr::operator[]( int index ) const
\r
362 // don't include the '/0' in the test, because technically, it's out of bounds
\r
363 assert( ( index >= 0 ) && ( index < m_data->len ) );
\r
365 // In release mode, give them a null character
\r
366 // don't include the '/0' in the test, because technically, it's out of bounds
\r
367 if ( ( index < 0 ) || ( index >= m_data->len ) )
\r
372 return m_data->data[ index ];
\r
375 inline char& idStr::operator[]
\r
381 // Used for result for invalid indices
\r
382 static char dummy = 0;
\r
385 // We don't know if they'll write to it or not
\r
386 // if it's not a const object
\r
387 EnsureDataWritable ();
\r
392 // don't include the '/0' in the test, because technically, it's out of bounds
\r
393 assert( ( index >= 0 ) && ( index < m_data->len ) );
\r
395 // In release mode, let them change a safe variable
\r
396 // don't include the '/0' in the test, because technically, it's out of bounds
\r
397 if ( ( index < 0 ) || ( index >= m_data->len ) )
\r
402 return m_data->data[ index ];
\r
405 inline void idStr::operator=
\r
411 // adding the reference before deleting our current reference prevents
\r
412 // us from deleting our string if we are copying from ourself
\r
413 text.m_data->AddRef();
\r
415 m_data = text.m_data;
\r
418 inline void idStr::operator=
\r
430 // safe behaviour if NULL
\r
431 EnsureAlloced ( 1, false );
\r
432 m_data->data[0] = 0;
\r
439 len = strlen ( text );
\r
440 EnsureAlloced( len + 1, false );
\r
441 strcpy ( m_data->data, text );
\r
446 if ( text == m_data->data )
\r
447 return; // Copying same thing. Punt.
\r
449 // If we alias and I don't do this, I could corrupt other strings... This
\r
450 // will get called with EnsureAlloced anyway
\r
451 EnsureDataWritable ();
\r
453 // Now we need to check if we're aliasing..
\r
454 if ( text >= m_data->data && text <= m_data->data + m_data->len )
\r
456 // Great, we're aliasing. We're copying from inside ourselves.
\r
457 // This means that I don't have to ensure that anything is alloced,
\r
458 // though I'll assert just in case.
\r
459 int diff = text - m_data->data;
\r
462 assert ( strlen ( text ) < (unsigned) m_data->len );
\r
464 for ( i = 0; text[i]; i++ )
\r
466 m_data->data[i] = text[i];
\r
469 m_data->data[i] = 0;
\r
471 m_data->len -= diff;
\r
476 len = strlen( text );
\r
477 EnsureAlloced ( len + 1, false );
\r
478 strcpy( m_data->data, text );
\r
482 inline idStr operator+
\r
491 result.append( b );
\r
496 inline idStr operator+
\r
505 result.append( b );
\r
510 inline idStr operator+
\r
519 result.append( b );
\r
524 inline idStr operator+
\r
533 result.append( b ? "true" : "false" );
\r
538 inline idStr operator+
\r
553 inline idStr& idStr::operator+=
\r
563 inline idStr& idStr::operator+=
\r
573 inline idStr& idStr::operator+=
\r
588 inline idStr& idStr::operator+=
\r
594 append( a ? "true" : "false" );
\r
598 inline bool operator==
\r
605 return ( !strcmp( a.c_str(), b.c_str() ) );
\r
608 inline bool operator==
\r
620 return ( !strcmp( a.c_str(), b ) );
\r
623 inline bool operator==
\r
635 return ( !strcmp( a, b.c_str() ) );
\r
638 inline bool operator!=
\r
645 return !( a == b );
\r
648 inline bool operator!=
\r
655 return !( a == b );
\r
658 inline bool operator!=
\r
665 return !( a == b );
\r
668 inline int idStr::icmpn
\r
678 return idStr::icmpn( m_data->data, text, n );
\r
681 inline int idStr::icmpn
\r
683 const idStr& text,
\r
689 assert( text.m_data );
\r
691 return idStr::icmpn( m_data->data, text.m_data->data, n );
\r
694 inline int idStr::icmp
\r
703 return idStr::icmp( m_data->data, text );
\r
706 inline int idStr::icmp
\r
712 assert( c_str () );
\r
713 assert( text.c_str () );
\r
715 return idStr::icmp( c_str () , text.c_str () );
\r
718 inline int idStr::cmp
\r
727 return idStr::cmp( m_data->data, text );
\r
730 inline int idStr::cmp
\r
736 assert( c_str () );
\r
737 assert( text.c_str () );
\r
739 return idStr::cmp( c_str () , text.c_str () );
\r
742 inline int idStr::cmpn
\r
749 assert( c_str () );
\r
752 return idStr::cmpn( c_str () , text, n );
\r
755 inline int idStr::cmpn
\r
757 const idStr& text,
\r
762 assert( c_str () );
\r
763 assert( text.c_str () );
\r
765 return idStr::cmpn( c_str () , text.c_str () , n );
\r
768 inline void idStr::tolower
\r
776 EnsureDataWritable ();
\r
778 idStr::tolower( m_data->data );
\r
781 inline void idStr::toupper
\r
789 EnsureDataWritable ();
\r
791 idStr::toupper( m_data->data );
\r
794 inline bool idStr::isNumeric
\r
801 return idStr::isNumeric( m_data->data );
\r
804 inline idStr::operator const char *() {
\r
808 inline idStr::operator const char *
\r