-/*\r
-Copyright (C) 1999-2007 id Software, Inc. and contributors.\r
-For a list of contributors, see the accompanying CONTRIBUTORS file.\r
-\r
-This file is part of GtkRadiant.\r
-\r
-GtkRadiant is free software; you can redistribute it and/or modify\r
-it under the terms of the GNU General Public License as published by\r
-the Free Software Foundation; either version 2 of the License, or\r
-(at your option) any later version.\r
-\r
-GtkRadiant is distributed in the hope that it will be useful,\r
-but WITHOUT ANY WARRANTY; without even the implied warranty of\r
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
-GNU General Public License for more details.\r
-\r
-You should have received a copy of the GNU General Public License\r
-along with GtkRadiant; if not, write to the Free Software\r
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA\r
-*/\r
-\r
-//need to rewrite this\r
-\r
-#ifndef __UTIL_STR_H__\r
-#define __UTIL_STR_H__\r
-\r
-#include <assert.h>\r
-#include <string.h>\r
-#include <stdio.h>\r
-\r
-#ifdef _WIN32\r
-#pragma warning(disable : 4710) // function 'blah' not inlined\r
-#endif\r
-\r
-void TestStringClass ();\r
-\r
-class strdata\r
- {\r
- public:\r
- strdata () : len( 0 ), refcount ( 0 ), data ( NULL ), alloced ( 0 ) {}\r
- ~strdata () \r
- {\r
- if ( data )\r
- delete [] data;\r
- }\r
-\r
- void AddRef () { refcount++; }\r
- bool DelRef () // True if killed\r
- {\r
- refcount--;\r
- if ( refcount < 0 )\r
- {\r
- delete this;\r
- return true;\r
- }\r
- \r
- return false;\r
- }\r
-\r
- int len;\r
- int refcount;\r
- char *data;\r
- int alloced;\r
- };\r
-\r
-class idStr {\r
-protected:\r
- strdata *m_data;\r
- void EnsureAlloced ( int, bool keepold = true );\r
- void EnsureDataWritable ();\r
-\r
-public:\r
- ~idStr();\r
- idStr();\r
- idStr( const char *text );\r
- idStr( const idStr& string );\r
- idStr( const idStr string, int start, int end );\r
- idStr( const char ch );\r
- idStr( const int num );\r
- idStr( const float num );\r
- idStr( const unsigned num );\r
- int length( void ) const;\r
- int allocated( void ) const;\r
- const char * c_str( void ) const;\r
-\r
- void append( const char *text );\r
- void append( const idStr& text );\r
- char operator[]( int index ) const;\r
- char& operator[]( int index );\r
-\r
- void operator=( const idStr& text );\r
- void operator=( const char *text );\r
-\r
- friend idStr operator+( const idStr& a, const idStr& b );\r
- friend idStr operator+( const idStr& a, const char *b );\r
- friend idStr operator+( const char *a, const idStr& b );\r
-\r
- friend idStr operator+( const idStr& a, const float b );\r
- friend idStr operator+( const idStr& a, const int b );\r
- friend idStr operator+( const idStr& a, const unsigned b );\r
- friend idStr operator+( const idStr& a, const bool b );\r
- friend idStr operator+( const idStr& a, const char b );\r
-\r
- idStr& operator+=( const idStr& a );\r
- idStr& operator+=( const char *a );\r
- idStr& operator+=( const float a );\r
- idStr& operator+=( const char a );\r
- idStr& operator+=( const int a );\r
- idStr& operator+=( const unsigned a );\r
- idStr& operator+=( const bool a );\r
-\r
- friend bool operator==( const idStr& a, const idStr& b );\r
- friend bool operator==( const idStr& a, const char *b );\r
- friend bool operator==( const char *a, const idStr& b );\r
-\r
- friend bool operator!=( const idStr& a, const idStr& b );\r
- friend bool operator!=( const idStr& a, const char *b );\r
- friend bool operator!=( const char *a, const idStr& b );\r
-\r
- operator const char * () const;\r
- operator const char * ();\r
-\r
- int icmpn( const char *text, int n ) const;\r
- int icmpn( const idStr& text, int n ) const;\r
- int icmp( const char *text ) const;\r
- int icmp( const idStr& text ) const;\r
- int cmpn( const char *text, int n ) const;\r
- int cmpn( const idStr& text, int n ) const;\r
- int cmp( const char *text ) const;\r
- int cmp( const idStr& text ) const;\r
-\r
- void tolower( void );\r
- void toupper( void );\r
-\r
- static char *tolower( char *s1 );\r
- static char *toupper( char *s1 );\r
-\r
- static int icmpn( const char *s1, const char *s2, int n );\r
- static int icmp( const char *s1, const char *s2 );\r
- static int cmpn( const char *s1, const char *s2, int n );\r
- static int cmp( const char *s1, const char *s2 );\r
-\r
- static void snprintf ( char *dst, int size, const char *fmt, ... );\r
-\r
- static bool isNumeric( const char *str );\r
- bool isNumeric( void ) const;\r
-\r
- void CapLength ( int );\r
-\r
- void BackSlashesToSlashes ();\r
-\r
-};\r
-\r
-inline idStr::~idStr()\r
- {\r
- if ( m_data )\r
- {\r
- m_data->DelRef ();\r
- m_data = NULL;\r
- }\r
- }\r
-\r
-inline idStr::idStr() : m_data ( NULL )\r
- {\r
- EnsureAlloced ( 1 );\r
- m_data->data[ 0 ] = 0;\r
- }\r
-\r
-inline idStr::idStr\r
- (\r
- const char *text\r
- ) : m_data ( NULL )\r
-\r
- {\r
- int len;\r
-\r
- assert( text );\r
-\r
- if ( text )\r
- {\r
- len = strlen( text );\r
- EnsureAlloced ( len + 1 );\r
- strcpy( m_data->data, text );\r
- m_data->len = len;\r
- }\r
- else\r
- {\r
- EnsureAlloced ( 1 );\r
- m_data->data[ 0 ] = 0;\r
- m_data->len = 0;\r
- }\r
- }\r
-\r
-inline idStr::idStr\r
- (\r
- const idStr& text\r
- ) : m_data ( NULL )\r
-\r
- {\r
- m_data = text.m_data;\r
- m_data->AddRef ();\r
- }\r
-\r
-inline idStr::idStr\r
- (\r
- const idStr text, \r
- int start,\r
- int end\r
- ) : m_data ( NULL )\r
-\r
- {\r
- int i;\r
- int len;\r
-\r
- if ( end > text.length() )\r
- {\r
- end = text.length();\r
- }\r
-\r
- if ( start > text.length() )\r
- {\r
- start = text.length();\r
- }\r
-\r
- len = end - start;\r
- if ( len < 0 )\r
- {\r
- len = 0;\r
- }\r
-\r
- EnsureAlloced ( len + 1 );\r
-\r
- for( i = 0; i < len; i++ )\r
- {\r
- m_data->data[ i ] = text[ start + i ];\r
- }\r
-\r
- m_data->data[ len ] = 0;\r
- m_data->len = len;\r
- }\r
-\r
-inline idStr::idStr\r
- (\r
- const char ch\r
- ) : m_data ( NULL )\r
-\r
- {\r
- EnsureAlloced ( 2 );\r
-\r
- m_data->data[ 0 ] = ch;\r
- m_data->data[ 1 ] = 0;\r
- m_data->len = 1;\r
- }\r
-\r
-inline idStr::idStr\r
- (\r
- const float num\r
- ) : m_data ( NULL )\r
-\r
- {\r
- char text[ 32 ];\r
- int len;\r
-\r
- sprintf( text, "%.3f", num );\r
- len = strlen( text );\r
- EnsureAlloced( len + 1 );\r
- strcpy( m_data->data, text );\r
- m_data->len = len;\r
- }\r
-\r
-inline idStr::idStr\r
- (\r
- const int num\r
- ) : m_data ( NULL )\r
-\r
- {\r
- char text[ 32 ];\r
- int len;\r
-\r
- sprintf( text, "%d", num );\r
- len = strlen( text );\r
- EnsureAlloced( len + 1 );\r
- strcpy( m_data->data, text );\r
- m_data->len = len;\r
- }\r
-\r
-inline idStr::idStr\r
- (\r
- const unsigned num\r
- ) : m_data ( NULL )\r
-\r
- {\r
- char text[ 32 ];\r
- int len;\r
-\r
- sprintf( text, "%u", num );\r
- len = strlen( text );\r
- EnsureAlloced( len + 1 );\r
- strcpy( m_data->data, text );\r
- m_data->len = len;\r
- }\r
-\r
-inline int idStr::length( void ) const\r
- {\r
- return ( m_data != NULL ) ? m_data->len : 0;\r
- }\r
-\r
-inline int idStr::allocated( void ) const\r
- {\r
- return ( m_data != NULL ) ? m_data->alloced + sizeof( *m_data ) : 0;\r
- }\r
-\r
-inline const char *idStr::c_str( void ) const\r
- {\r
- assert( m_data );\r
-\r
- return m_data->data;\r
- }\r
-\r
-inline void idStr::append\r
- (\r
- const char *text\r
- )\r
-\r
- {\r
- int len;\r
-\r
- assert( text );\r
-\r
- if ( text )\r
- {\r
- len = length() + strlen( text );\r
- EnsureAlloced( len + 1 );\r
-\r
- strcat( m_data->data, text );\r
- m_data->len = len;\r
- }\r
- }\r
-\r
-inline void idStr::append\r
- (\r
- const idStr& text\r
- )\r
-\r
- {\r
- int len;\r
-\r
- len = length() + text.length();\r
- EnsureAlloced ( len + 1 );\r
-\r
- strcat ( m_data->data, text.c_str () );\r
- m_data->len = len;\r
- }\r
-\r
-inline char idStr::operator[]( int index ) const\r
- {\r
- assert ( m_data );\r
- \r
- if ( !m_data )\r
- return 0;\r
-\r
- // don't include the '/0' in the test, because technically, it's out of bounds\r
- assert( ( index >= 0 ) && ( index < m_data->len ) );\r
-\r
- // In release mode, give them a null character\r
- // don't include the '/0' in the test, because technically, it's out of bounds\r
- if ( ( index < 0 ) || ( index >= m_data->len ) )\r
- {\r
- return 0;\r
- }\r
-\r
- return m_data->data[ index ];\r
- }\r
-\r
-inline char& idStr::operator[]\r
- (\r
- int index\r
- )\r
-\r
- {\r
- // Used for result for invalid indices\r
- static char dummy = 0;\r
- assert ( m_data );\r
-\r
- // We don't know if they'll write to it or not\r
- // if it's not a const object\r
- EnsureDataWritable ();\r
-\r
- if ( !m_data )\r
- return dummy;\r
-\r
- // don't include the '/0' in the test, because technically, it's out of bounds\r
- assert( ( index >= 0 ) && ( index < m_data->len ) );\r
-\r
- // In release mode, let them change a safe variable\r
- // don't include the '/0' in the test, because technically, it's out of bounds\r
- if ( ( index < 0 ) || ( index >= m_data->len ) )\r
- {\r
- return dummy;\r
- }\r
-\r
- return m_data->data[ index ];\r
- }\r
-\r
-inline void idStr::operator=\r
- (\r
- const idStr& text\r
- )\r
-\r
- {\r
- // adding the reference before deleting our current reference prevents\r
- // us from deleting our string if we are copying from ourself\r
- text.m_data->AddRef();\r
- m_data->DelRef();\r
- m_data = text.m_data;\r
- }\r
-\r
-inline void idStr::operator=\r
- (\r
- const char *text\r
- )\r
-\r
- {\r
- int len;\r
-\r
- assert( text );\r
-\r
- if ( !text )\r
- {\r
- // safe behaviour if NULL\r
- EnsureAlloced ( 1, false );\r
- m_data->data[0] = 0;\r
- m_data->len = 0;\r
- return;\r
- }\r
-\r
- if ( !m_data )\r
- {\r
- len = strlen ( text );\r
- EnsureAlloced( len + 1, false );\r
- strcpy ( m_data->data, text );\r
- m_data->len = len;\r
- return;\r
- }\r
-\r
- if ( text == m_data->data )\r
- return; // Copying same thing. Punt.\r
-\r
- // If we alias and I don't do this, I could corrupt other strings... This \r
- // will get called with EnsureAlloced anyway\r
- EnsureDataWritable ();\r
-\r
- // Now we need to check if we're aliasing..\r
- if ( text >= m_data->data && text <= m_data->data + m_data->len )\r
- {\r
- // Great, we're aliasing. We're copying from inside ourselves.\r
- // This means that I don't have to ensure that anything is alloced,\r
- // though I'll assert just in case.\r
- int diff = text - m_data->data;\r
- int i;\r
-\r
- assert ( strlen ( text ) < (unsigned) m_data->len );\r
- \r
- for ( i = 0; text[i]; i++ )\r
- {\r
- m_data->data[i] = text[i];\r
- }\r
-\r
- m_data->data[i] = 0;\r
-\r
- m_data->len -= diff;\r
-\r
- return;\r
- }\r
-\r
- len = strlen( text );\r
- EnsureAlloced ( len + 1, false );\r
- strcpy( m_data->data, text );\r
- m_data->len = len;\r
- }\r
-\r
-inline idStr operator+\r
- (\r
- const idStr& a,\r
- const idStr& b\r
- )\r
-\r
- {\r
- idStr result( a );\r
-\r
- result.append( b );\r
-\r
- return result;\r
- }\r
-\r
-inline idStr operator+\r
- (\r
- const idStr& a,\r
- const char *b\r
- )\r
-\r
- {\r
- idStr result( a );\r
-\r
- result.append( b );\r
-\r
- return result;\r
- }\r
-\r
-inline idStr operator+\r
- (\r
- const char *a,\r
- const idStr& b\r
- )\r
-\r
- {\r
- idStr result( a );\r
-\r
- result.append( b );\r
-\r
- return result;\r
- }\r
-\r
-inline idStr operator+\r
- (\r
- const idStr& a,\r
- const bool b\r
- )\r
-\r
- {\r
- idStr result( a );\r
-\r
- result.append( b ? "true" : "false" );\r
-\r
- return result;\r
- }\r
-\r
-inline idStr operator+\r
- (\r
- const idStr& a,\r
- const char b\r
- )\r
-\r
- {\r
- char text[ 2 ];\r
-\r
- text[ 0 ] = b;\r
- text[ 1 ] = 0;\r
-\r
- return a + text;\r
- }\r
-\r
-inline idStr& idStr::operator+=\r
- (\r
- const idStr& a\r
- )\r
-\r
- {\r
- append( a );\r
- return *this;\r
- }\r
-\r
-inline idStr& idStr::operator+=\r
- (\r
- const char *a\r
- )\r
-\r
- {\r
- append( a );\r
- return *this;\r
- }\r
-\r
-inline idStr& idStr::operator+=\r
- (\r
- const char a\r
- )\r
-\r
- {\r
- char text[ 2 ];\r
-\r
- text[ 0 ] = a;\r
- text[ 1 ] = 0;\r
- append( text );\r
-\r
- return *this;\r
- }\r
-\r
-inline idStr& idStr::operator+=\r
- (\r
- const bool a\r
- )\r
-\r
- {\r
- append( a ? "true" : "false" );\r
- return *this;\r
- }\r
-\r
-inline bool operator==\r
- (\r
- const idStr& a,\r
- const idStr& b\r
- )\r
-\r
- {\r
- return ( !strcmp( a.c_str(), b.c_str() ) );\r
- }\r
-\r
-inline bool operator==\r
- (\r
- const idStr& a,\r
- const char *b\r
- )\r
-\r
- {\r
- assert( b );\r
- if ( !b )\r
- {\r
- return false;\r
- }\r
- return ( !strcmp( a.c_str(), b ) );\r
- }\r
-\r
-inline bool operator==\r
- (\r
- const char *a,\r
- const idStr& b\r
- )\r
-\r
- {\r
- assert( a );\r
- if ( !a )\r
- {\r
- return false;\r
- }\r
- return ( !strcmp( a, b.c_str() ) );\r
- }\r
-\r
-inline bool operator!=\r
- (\r
- const idStr& a,\r
- const idStr& b\r
- )\r
-\r
- {\r
- return !( a == b );\r
- }\r
-\r
-inline bool operator!=\r
- (\r
- const idStr& a,\r
- const char *b\r
- )\r
-\r
- {\r
- return !( a == b );\r
- }\r
-\r
-inline bool operator!=\r
- (\r
- const char *a,\r
- const idStr& b\r
- )\r
-\r
- {\r
- return !( a == b );\r
- }\r
-\r
-inline int idStr::icmpn\r
- (\r
- const char *text, \r
- int n\r
- ) const\r
-\r
- {\r
- assert( m_data );\r
- assert( text );\r
-\r
- return idStr::icmpn( m_data->data, text, n );\r
- }\r
-\r
-inline int idStr::icmpn\r
- (\r
- const idStr& text, \r
- int n\r
- ) const\r
-\r
- {\r
- assert( m_data );\r
- assert( text.m_data );\r
-\r
- return idStr::icmpn( m_data->data, text.m_data->data, n );\r
- }\r
-\r
-inline int idStr::icmp\r
- (\r
- const char *text\r
- ) const\r
-\r
- {\r
- assert( m_data );\r
- assert( text );\r
-\r
- return idStr::icmp( m_data->data, text );\r
- }\r
-\r
-inline int idStr::icmp\r
- (\r
- const idStr& text\r
- ) const\r
-\r
- {\r
- assert( c_str () );\r
- assert( text.c_str () );\r
-\r
- return idStr::icmp( c_str () , text.c_str () );\r
- }\r
-\r
-inline int idStr::cmp\r
- (\r
- const char *text\r
- ) const\r
-\r
- {\r
- assert( m_data );\r
- assert( text );\r
-\r
- return idStr::cmp( m_data->data, text );\r
- }\r
-\r
-inline int idStr::cmp\r
- (\r
- const idStr& text\r
- ) const\r
-\r
- {\r
- assert( c_str () );\r
- assert( text.c_str () );\r
-\r
- return idStr::cmp( c_str () , text.c_str () );\r
- }\r
-\r
-inline int idStr::cmpn\r
- (\r
- const char *text, \r
- int n\r
- ) const\r
-\r
- {\r
- assert( c_str () );\r
- assert( text );\r
-\r
- return idStr::cmpn( c_str () , text, n );\r
- }\r
-\r
-inline int idStr::cmpn\r
- (\r
- const idStr& text, \r
- int n\r
- ) const\r
-\r
- {\r
- assert( c_str () );\r
- assert( text.c_str () );\r
-\r
- return idStr::cmpn( c_str () , text.c_str () , n );\r
- }\r
-\r
-inline void idStr::tolower\r
- (\r
- void\r
- )\r
-\r
- {\r
- assert( m_data );\r
-\r
- EnsureDataWritable ();\r
-\r
- idStr::tolower( m_data->data );\r
- }\r
-\r
-inline void idStr::toupper\r
- (\r
- void\r
- )\r
-\r
- {\r
- assert( m_data );\r
-\r
- EnsureDataWritable ();\r
-\r
- idStr::toupper( m_data->data );\r
- }\r
-\r
-inline bool idStr::isNumeric\r
- (\r
- void\r
- ) const\r
-\r
- {\r
- assert( m_data );\r
- return idStr::isNumeric( m_data->data );\r
- }\r
-\r
-inline idStr::operator const char *() {\r
- return c_str();\r
-}\r
-\r
-inline idStr::operator const char *\r
- (\r
- void\r
- ) const\r
-\r
- {\r
- return c_str ();\r
- }\r
-\r
-#endif\r
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+GtkRadiant is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+//need to rewrite this
+
+#ifndef __UTIL_STR_H__
+#define __UTIL_STR_H__
+
+#include <assert.h>
+#include <string.h>
+#include <stdio.h>
+
+#ifdef _WIN32
+#pragma warning(disable : 4710) // function 'blah' not inlined
+#endif
+
+void TestStringClass ();
+
+class strdata
+ {
+ public:
+ strdata () : len( 0 ), refcount ( 0 ), data ( NULL ), alloced ( 0 ) {}
+ ~strdata ()
+ {
+ if ( data )
+ delete [] data;
+ }
+
+ void AddRef () { refcount++; }
+ bool DelRef () // True if killed
+ {
+ refcount--;
+ if ( refcount < 0 )
+ {
+ delete this;
+ return true;
+ }
+
+ return false;
+ }
+
+ int len;
+ int refcount;
+ char *data;
+ int alloced;
+ };
+
+class idStr {
+protected:
+ strdata *m_data;
+ void EnsureAlloced ( int, bool keepold = true );
+ void EnsureDataWritable ();
+
+public:
+ ~idStr();
+ idStr();
+ idStr( const char *text );
+ idStr( const idStr& string );
+ idStr( const idStr string, int start, int end );
+ idStr( const char ch );
+ idStr( const int num );
+ idStr( const float num );
+ idStr( const unsigned num );
+ int length( void ) const;
+ int allocated( void ) const;
+ const char * c_str( void ) const;
+
+ void append( const char *text );
+ void append( const idStr& text );
+ 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 );
+
+ 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 );
+
+ 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 );
+
+ operator const char * () const;
+ operator const char * ();
+
+ int icmpn( const char *text, int n ) const;
+ int icmpn( const idStr& text, int n ) const;
+ int icmp( const char *text ) const;
+ int icmp( const idStr& text ) const;
+ int cmpn( const char *text, int n ) const;
+ int cmpn( const idStr& text, int n ) const;
+ int cmp( const char *text ) const;
+ int cmp( const idStr& text ) const;
+
+ void tolower( void );
+ void toupper( void );
+
+ static char *tolower( char *s1 );
+ static char *toupper( char *s1 );
+
+ static int icmpn( const char *s1, const char *s2, int n );
+ static int icmp( const char *s1, const char *s2 );
+ static int cmpn( const char *s1, const char *s2, int n );
+ static int cmp( const char *s1, const char *s2 );
+
+ static void snprintf ( char *dst, int size, const char *fmt, ... );
+
+ static bool isNumeric( const char *str );
+ bool isNumeric( void ) const;
+
+ void CapLength ( int );
+
+ void BackSlashesToSlashes ();
+
+};
+
+inline idStr::~idStr()
+ {
+ if ( m_data )
+ {
+ m_data->DelRef ();
+ m_data = NULL;
+ }
+ }
+
+inline idStr::idStr() : m_data ( NULL )
+ {
+ EnsureAlloced ( 1 );
+ m_data->data[ 0 ] = 0;
+ }
+
+inline idStr::idStr
+ (
+ const char *text
+ ) : m_data ( NULL )
+
+ {
+ int len;
+
+ assert( text );
+
+ if ( text )
+ {
+ len = strlen( text );
+ EnsureAlloced ( len + 1 );
+ strcpy( m_data->data, text );
+ m_data->len = len;
+ }
+ else
+ {
+ EnsureAlloced ( 1 );
+ m_data->data[ 0 ] = 0;
+ m_data->len = 0;
+ }
+ }
+
+inline idStr::idStr
+ (
+ const idStr& text
+ ) : m_data ( NULL )
+
+ {
+ m_data = text.m_data;
+ m_data->AddRef ();
+ }
+
+inline idStr::idStr
+ (
+ const idStr text,
+ int start,
+ int end
+ ) : m_data ( NULL )
+
+ {
+ int i;
+ int len;
+
+ if ( end > text.length() )
+ {
+ end = text.length();
+ }
+
+ if ( start > text.length() )
+ {
+ start = text.length();
+ }
+
+ len = end - start;
+ if ( len < 0 )
+ {
+ len = 0;
+ }
+
+ EnsureAlloced ( len + 1 );
+
+ for( i = 0; i < len; i++ )
+ {
+ m_data->data[ i ] = text[ start + i ];
+ }
+
+ m_data->data[ len ] = 0;
+ m_data->len = len;
+ }
+
+inline idStr::idStr
+ (
+ const char ch
+ ) : m_data ( NULL )
+
+ {
+ EnsureAlloced ( 2 );
+
+ m_data->data[ 0 ] = ch;
+ m_data->data[ 1 ] = 0;
+ m_data->len = 1;
+ }
+
+inline idStr::idStr
+ (
+ const float num
+ ) : m_data ( NULL )
+
+ {
+ char text[ 32 ];
+ int len;
+
+ sprintf( text, "%.3f", num );
+ len = strlen( text );
+ EnsureAlloced( len + 1 );
+ strcpy( m_data->data, text );
+ m_data->len = len;
+ }
+
+inline idStr::idStr
+ (
+ const int num
+ ) : m_data ( NULL )
+
+ {
+ char text[ 32 ];
+ int len;
+
+ sprintf( text, "%d", num );
+ len = strlen( text );
+ EnsureAlloced( len + 1 );
+ strcpy( m_data->data, text );
+ m_data->len = len;
+ }
+
+inline idStr::idStr
+ (
+ const unsigned num
+ ) : m_data ( NULL )
+
+ {
+ char text[ 32 ];
+ int len;
+
+ sprintf( text, "%u", num );
+ len = strlen( text );
+ EnsureAlloced( len + 1 );
+ strcpy( m_data->data, text );
+ m_data->len = len;
+ }
+
+inline int idStr::length( void ) const
+ {
+ return ( m_data != NULL ) ? m_data->len : 0;
+ }
+
+inline int idStr::allocated( void ) const
+ {
+ return ( m_data != NULL ) ? m_data->alloced + sizeof( *m_data ) : 0;
+ }
+
+inline const char *idStr::c_str( void ) const
+ {
+ assert( m_data );
+
+ return m_data->data;
+ }
+
+inline void idStr::append
+ (
+ const char *text
+ )
+
+ {
+ int len;
+
+ assert( text );
+
+ if ( text )
+ {
+ len = length() + strlen( text );
+ EnsureAlloced( len + 1 );
+
+ strcat( m_data->data, text );
+ m_data->len = len;
+ }
+ }
+
+inline void idStr::append
+ (
+ const idStr& text
+ )
+
+ {
+ int len;
+
+ len = length() + text.length();
+ EnsureAlloced ( len + 1 );
+
+ strcat ( m_data->data, text.c_str () );
+ m_data->len = len;
+ }
+
+inline char idStr::operator[]( int index ) const
+ {
+ assert ( m_data );
+
+ if ( !m_data )
+ return 0;
+
+ // don't include the '/0' in the test, because technically, it's out of bounds
+ assert( ( index >= 0 ) && ( index < m_data->len ) );
+
+ // In release mode, give them a null character
+ // don't include the '/0' in the test, because technically, it's out of bounds
+ if ( ( index < 0 ) || ( index >= m_data->len ) )
+ {
+ return 0;
+ }
+
+ return m_data->data[ index ];
+ }
+
+inline char& idStr::operator[]
+ (
+ int index
+ )
+
+ {
+ // Used for result for invalid indices
+ static char dummy = 0;
+ assert ( m_data );
+
+ // We don't know if they'll write to it or not
+ // if it's not a const object
+ EnsureDataWritable ();
+
+ if ( !m_data )
+ return dummy;
+
+ // don't include the '/0' in the test, because technically, it's out of bounds
+ assert( ( index >= 0 ) && ( index < m_data->len ) );
+
+ // In release mode, let them change a safe variable
+ // don't include the '/0' in the test, because technically, it's out of bounds
+ if ( ( index < 0 ) || ( index >= m_data->len ) )
+ {
+ return dummy;
+ }
+
+ return m_data->data[ index ];
+ }
+
+inline void idStr::operator=
+ (
+ const idStr& text
+ )
+
+ {
+ // adding the reference before deleting our current reference prevents
+ // us from deleting our string if we are copying from ourself
+ text.m_data->AddRef();
+ m_data->DelRef();
+ m_data = text.m_data;
+ }
+
+inline void idStr::operator=
+ (
+ const char *text
+ )
+
+ {
+ int len;
+
+ assert( text );
+
+ if ( !text )
+ {
+ // safe behaviour if NULL
+ EnsureAlloced ( 1, false );
+ m_data->data[0] = 0;
+ m_data->len = 0;
+ return;
+ }
+
+ if ( !m_data )
+ {
+ len = strlen ( text );
+ EnsureAlloced( len + 1, false );
+ strcpy ( m_data->data, text );
+ m_data->len = len;
+ return;
+ }
+
+ if ( text == m_data->data )
+ return; // Copying same thing. Punt.
+
+ // If we alias and I don't do this, I could corrupt other strings... This
+ // will get called with EnsureAlloced anyway
+ EnsureDataWritable ();
+
+ // Now we need to check if we're aliasing..
+ if ( text >= m_data->data && text <= m_data->data + m_data->len )
+ {
+ // Great, we're aliasing. We're copying from inside ourselves.
+ // This means that I don't have to ensure that anything is alloced,
+ // though I'll assert just in case.
+ int diff = text - m_data->data;
+ int i;
+
+ assert ( strlen ( text ) < (unsigned) m_data->len );
+
+ for ( i = 0; text[i]; i++ )
+ {
+ m_data->data[i] = text[i];
+ }
+
+ m_data->data[i] = 0;
+
+ m_data->len -= diff;
+
+ return;
+ }
+
+ len = strlen( text );
+ EnsureAlloced ( len + 1, false );
+ strcpy( m_data->data, text );
+ m_data->len = len;
+ }
+
+inline idStr operator+
+ (
+ const idStr& a,
+ const idStr& b
+ )
+
+ {
+ idStr result( a );
+
+ result.append( b );
+
+ return result;
+ }
+
+inline idStr operator+
+ (
+ const idStr& a,
+ const char *b
+ )
+
+ {
+ idStr result( a );
+
+ result.append( b );
+
+ return result;
+ }
+
+inline idStr operator+
+ (
+ const char *a,
+ const idStr& b
+ )
+
+ {
+ idStr result( a );
+
+ result.append( b );
+
+ return result;
+ }
+
+inline idStr operator+
+ (
+ const idStr& a,
+ const bool b
+ )
+
+ {
+ idStr result( a );
+
+ result.append( b ? "true" : "false" );
+
+ return result;
+ }
+
+inline idStr operator+
+ (
+ const idStr& a,
+ const char b
+ )
+
+ {
+ char text[ 2 ];
+
+ text[ 0 ] = b;
+ text[ 1 ] = 0;
+
+ return a + text;
+ }
+
+inline idStr& idStr::operator+=
+ (
+ const idStr& a
+ )
+
+ {
+ append( a );
+ return *this;
+ }
+
+inline idStr& idStr::operator+=
+ (
+ const char *a
+ )
+
+ {
+ append( a );
+ return *this;
+ }
+
+inline idStr& idStr::operator+=
+ (
+ const char a
+ )
+
+ {
+ char text[ 2 ];
+
+ text[ 0 ] = a;
+ text[ 1 ] = 0;
+ append( text );
+
+ return *this;
+ }
+
+inline idStr& idStr::operator+=
+ (
+ const bool a
+ )
+
+ {
+ append( a ? "true" : "false" );
+ return *this;
+ }
+
+inline bool operator==
+ (
+ const idStr& a,
+ const idStr& b
+ )
+
+ {
+ return ( !strcmp( a.c_str(), b.c_str() ) );
+ }
+
+inline bool operator==
+ (
+ const idStr& a,
+ const char *b
+ )
+
+ {
+ assert( b );
+ if ( !b )
+ {
+ return false;
+ }
+ return ( !strcmp( a.c_str(), b ) );
+ }
+
+inline bool operator==
+ (
+ const char *a,
+ const idStr& b
+ )
+
+ {
+ assert( a );
+ if ( !a )
+ {
+ return false;
+ }
+ return ( !strcmp( a, b.c_str() ) );
+ }
+
+inline bool operator!=
+ (
+ const idStr& a,
+ const idStr& b
+ )
+
+ {
+ return !( a == b );
+ }
+
+inline bool operator!=
+ (
+ const idStr& a,
+ const char *b
+ )
+
+ {
+ return !( a == b );
+ }
+
+inline bool operator!=
+ (
+ const char *a,
+ const idStr& b
+ )
+
+ {
+ return !( a == b );
+ }
+
+inline int idStr::icmpn
+ (
+ const char *text,
+ int n
+ ) const
+
+ {
+ assert( m_data );
+ assert( text );
+
+ return idStr::icmpn( m_data->data, text, n );
+ }
+
+inline int idStr::icmpn
+ (
+ const idStr& text,
+ int n
+ ) const
+
+ {
+ assert( m_data );
+ assert( text.m_data );
+
+ return idStr::icmpn( m_data->data, text.m_data->data, n );
+ }
+
+inline int idStr::icmp
+ (
+ const char *text
+ ) const
+
+ {
+ assert( m_data );
+ assert( text );
+
+ return idStr::icmp( m_data->data, text );
+ }
+
+inline int idStr::icmp
+ (
+ const idStr& text
+ ) const
+
+ {
+ assert( c_str () );
+ assert( text.c_str () );
+
+ return idStr::icmp( c_str () , text.c_str () );
+ }
+
+inline int idStr::cmp
+ (
+ const char *text
+ ) const
+
+ {
+ assert( m_data );
+ assert( text );
+
+ return idStr::cmp( m_data->data, text );
+ }
+
+inline int idStr::cmp
+ (
+ const idStr& text
+ ) const
+
+ {
+ assert( c_str () );
+ assert( text.c_str () );
+
+ return idStr::cmp( c_str () , text.c_str () );
+ }
+
+inline int idStr::cmpn
+ (
+ const char *text,
+ int n
+ ) const
+
+ {
+ assert( c_str () );
+ assert( text );
+
+ return idStr::cmpn( c_str () , text, n );
+ }
+
+inline int idStr::cmpn
+ (
+ const idStr& text,
+ int n
+ ) const
+
+ {
+ assert( c_str () );
+ assert( text.c_str () );
+
+ return idStr::cmpn( c_str () , text.c_str () , n );
+ }
+
+inline void idStr::tolower
+ (
+ void
+ )
+
+ {
+ assert( m_data );
+
+ EnsureDataWritable ();
+
+ idStr::tolower( m_data->data );
+ }
+
+inline void idStr::toupper
+ (
+ void
+ )
+
+ {
+ assert( m_data );
+
+ EnsureDataWritable ();
+
+ idStr::toupper( m_data->data );
+ }
+
+inline bool idStr::isNumeric
+ (
+ void
+ ) const
+
+ {
+ assert( m_data );
+ return idStr::isNumeric( m_data->data );
+ }
+
+inline idStr::operator const char *() {
+ return c_str();
+}
+
+inline idStr::operator const char *
+ (
+ void
+ ) const
+
+ {
+ return c_str ();
+ }
+
+#endif