]> de.git.xonotic.org Git - xonotic/netradiant.git/blobdiff - libs/splines/util_str.cpp
more eol-style
[xonotic/netradiant.git] / libs / splines / util_str.cpp
index 436285ade1765ad69b9ba884988d44e61e96996f..ecacc7666884f9c5f45d8e94201b383dafd6dc30 100644 (file)
-/*\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
-#include "util_str.h"\r
-#include <stdlib.h>\r
-#include <ctype.h>\r
-#include <stdio.h>\r
-#include <stdarg.h>\r
-\r
-#ifdef _WIN32\r
-#pragma warning(disable : 4244)     // 'conversion' conversion from 'type1' to 'type2', possible loss of data\r
-#pragma warning(disable : 4710)     // function 'blah' not inlined\r
-#endif\r
-\r
-static const int STR_ALLOC_GRAN = 20;\r
-\r
-// screwy but intentional\r
-#ifdef __APPLE_BUG__\r
-char *idStr::__tolower\r
-#else\r
-char *idStr::tolower\r
-#endif\r
-   (\r
-   char *s1\r
-   )\r
-   \r
-   {\r
-   char *s;\r
-\r
-   s = s1;\r
-       while( *s )\r
-      {\r
-      *s = ::tolower( *s );\r
-               s++;\r
-          }\r
-   \r
-   return s1;\r
-   }\r
-\r
-// screwy but intentional\r
-#ifdef __APPLE_BUG__\r
-char *idStr::__toupper\r
-#else\r
-char *idStr::toupper\r
-#endif\r
-   (\r
-   char *s1\r
-   )\r
-   \r
-   {\r
-   char *s;\r
-\r
-   s = s1;\r
-       while( *s )\r
-      {\r
-      *s = ::toupper( *s );\r
-               s++;\r
-          }\r
-   \r
-   return s1;\r
-   }\r
-\r
-int idStr::icmpn\r
-   (\r
-   const char *s1, \r
-   const char *s2, \r
-   int n\r
-   )\r
-   \r
-   {\r
-       int c1;\r
-   int c2;\r
-       \r
-       do \r
-      {\r
-               c1 = *s1++;\r
-               c2 = *s2++;\r
-\r
-               if ( !n-- )\r
-         {\r
-         // idStrings are equal until end point\r
-                       return 0;\r
-                  }\r
-               \r
-               if ( c1 != c2 )\r
-         {\r
-                       if ( c1 >= 'a' && c1 <= 'z' )\r
-            {\r
-                               c1 -= ( 'a' - 'A' );\r
-                          }\r
-\r
-                       if ( c2 >= 'a' && c2 <= 'z' )\r
-            {\r
-                               c2 -= ( 'a' - 'A' );\r
-                          }\r
-\r
-                       if ( c1 < c2 )\r
-            {\r
-            // strings less than\r
-                               return -1;\r
-                          }\r
-         else if ( c1 > c2 ) \r
-            {\r
-            // strings greater than\r
-            return 1;\r
-            }\r
-                  }\r
-          } \r
-   while( c1 );\r
-       \r
-   // strings are equal\r
-       return 0;\r
-   }\r
-\r
-int idStr::icmp\r
-   (\r
-   const char *s1,\r
-   const char *s2\r
-   )\r
-   \r
-   {\r
-       int c1;\r
-   int c2;\r
-       \r
-       do \r
-      {\r
-               c1 = *s1++;\r
-               c2 = *s2++;\r
-\r
-               if ( c1 != c2 )\r
-         {\r
-                       if ( c1 >= 'a' && c1 <= 'z' )\r
-            {\r
-                               c1 -= ( 'a' - 'A' );\r
-                          }\r
-\r
-                       if ( c2 >= 'a' && c2 <= 'z' )\r
-            {\r
-                               c2 -= ( 'a' - 'A' );\r
-                          }\r
-\r
-                       if ( c1 < c2 )\r
-            {\r
-            // strings less than\r
-                               return -1;\r
-                          }\r
-         else if ( c1 > c2 ) \r
-            {\r
-            // strings greater than\r
-            return 1;\r
-            }\r
-                  }\r
-          } \r
-   while( c1 );\r
-       \r
-   // strings are equal\r
-       return 0;\r
-   }\r
-\r
-int idStr::cmpn\r
-   (\r
-   const char *s1, \r
-   const char *s2, \r
-   int n\r
-   )\r
-   \r
-   {\r
-       int c1;\r
-   int c2;\r
-       \r
-       do \r
-      {\r
-               c1 = *s1++;\r
-               c2 = *s2++;\r
-\r
-               if ( !n-- )\r
-         {\r
-         // strings are equal until end point\r
-                       return 0;\r
-                  }\r
-               \r
-               if ( c1 < c2 )\r
-         {\r
-         // strings less than\r
-                       return -1;\r
-                       }\r
-      else if ( c1 > c2 ) \r
-         {\r
-         // strings greater than\r
-         return 1;\r
-         }\r
-          } \r
-   while( c1 );\r
-       \r
-   // strings are equal\r
-       return 0;\r
-   }\r
-\r
-int idStr::cmp\r
-   (\r
-   const char *s1, \r
-   const char *s2\r
-   )\r
-   \r
-   {\r
-       int c1;\r
-   int c2;\r
-       \r
-       do \r
-      {\r
-               c1 = *s1++;\r
-               c2 = *s2++;\r
-\r
-               if ( c1 < c2 )\r
-         {\r
-         // strings less than\r
-                       return -1;\r
-                       }\r
-      else if ( c1 > c2 ) \r
-         {\r
-         // strings greater than\r
-         return 1;\r
-         }\r
-          } \r
-   while( c1 );\r
-       \r
-   // strings are equal\r
-       return 0;\r
-   }\r
-\r
-/*\r
-============\r
-IsNumeric\r
-\r
-Checks a string to see if it contains only numerical values.\r
-============\r
-*/\r
-bool idStr::isNumeric\r
-   (\r
-   const char *str\r
-   )\r
-\r
-   {\r
-       int len;\r
-       int i;\r
-       bool dot;\r
-\r
-       if ( *str == '-' )\r
-               {\r
-               str++;\r
-               }\r
-\r
-       dot = false;\r
-       len = strlen( str );\r
-       for( i = 0; i < len; i++ )\r
-               {\r
-               if ( !isdigit( str[ i ] ) )\r
-                       {\r
-                       if ( ( str[ i ] == '.' ) && !dot )\r
-                               {\r
-                               dot = true;\r
-                               continue;\r
-                               }\r
-                       return false;\r
-                       }\r
-               }\r
-\r
-       return true;\r
-   }\r
-\r
-idStr operator+\r
-   (\r
-   const idStr& a,\r
-   const float b\r
-   )\r
-\r
-   {\r
-   char text[ 20 ];\r
-\r
-       idStr result( a );\r
-\r
-   sprintf( text, "%f", b );\r
-       result.append( text );\r
-\r
-       return result;\r
-   }\r
-\r
-idStr operator+\r
-   (\r
-   const idStr& a,\r
-   const int b\r
-   )\r
-\r
-   {\r
-   char text[ 20 ];\r
-\r
-       idStr result( a );\r
-\r
-   sprintf( text, "%d", b );\r
-       result.append( text );\r
-\r
-       return result;\r
-   }\r
-\r
-idStr operator+\r
-   (\r
-   const idStr& a,\r
-   const unsigned b\r
-   )\r
-\r
-   {\r
-   char text[ 20 ];\r
-\r
-       idStr result( a );\r
-\r
-   sprintf( text, "%u", b );\r
-       result.append( text );\r
-\r
-       return result;\r
-   }\r
-\r
-idStr& idStr::operator+=\r
-       (\r
-       const float a\r
-       )\r
-\r
-       {\r
-   char text[ 20 ];\r
-\r
-   sprintf( text, "%f", a );\r
-       append( text );\r
-\r
-   return *this;\r
-       }\r
-\r
-idStr& idStr::operator+=\r
-       (\r
-       const int a\r
-       )\r
-\r
-       {\r
-   char text[ 20 ];\r
-\r
-   sprintf( text, "%d", a );\r
-       append( text );\r
-\r
-   return *this;\r
-       }\r
-\r
-idStr& idStr::operator+=\r
-       (\r
-       const unsigned a\r
-       )\r
-\r
-       {\r
-   char text[ 20 ];\r
-\r
-   sprintf( text, "%u", a );\r
-       append( text );\r
-\r
-   return *this;\r
-       }\r
-\r
-void idStr::CapLength \r
-   (\r
-   int newlen \r
-   )\r
-\r
-   {\r
-   assert ( m_data );\r
-   \r
-   if ( length() <= newlen )\r
-      return;\r
-\r
-   EnsureDataWritable ();\r
-\r
-   m_data->data[newlen] = 0;\r
-   m_data->len = newlen;\r
-   }\r
-\r
-void idStr::EnsureDataWritable \r
-   (\r
-   void\r
-   )\r
-\r
-   {\r
-   assert ( m_data );\r
-   strdata *olddata;\r
-   int len;\r
-\r
-   if ( !m_data->refcount )\r
-      return;\r
-\r
-   olddata = m_data;\r
-   len = length();\r
-\r
-   m_data = new strdata;\r
-\r
-   EnsureAlloced ( len + 1, false );\r
-   strncpy ( m_data->data, olddata->data, len+1 );\r
-   m_data->len = len;\r
-\r
-   olddata->DelRef ();\r
-   }\r
-\r
-void idStr::EnsureAlloced (int amount, bool keepold) {\r
-\r
-       if ( !m_data ) {\r
-      m_data = new strdata();\r
-       }\r
-   \r
-       // Now, let's make sure it's writable\r
-       EnsureDataWritable ();\r
-\r
-       char *newbuffer;\r
-       bool wasalloced = ( m_data->alloced != 0 );\r
-\r
-       if ( amount < m_data->alloced ) {\r
-               return;\r
-       }\r
-\r
-       assert ( amount );\r
-       if ( amount == 1 ) {\r
-               m_data->alloced = 1;\r
-       } else {\r
-               int newsize, mod;\r
-               mod = amount % STR_ALLOC_GRAN;\r
-               if ( !mod ) {\r
-                       newsize = amount;\r
-               } else {\r
-         newsize = amount + STR_ALLOC_GRAN - mod;\r
-               }\r
-               m_data->alloced = newsize;\r
-       }\r
-\r
-       newbuffer = new char[m_data->alloced];\r
-       if ( wasalloced && keepold ) {\r
-               strcpy ( newbuffer, m_data->data );\r
-       }\r
-\r
-       if ( m_data->data ) {\r
-               delete [] m_data->data;\r
-    }\r
-       m_data->data = newbuffer;\r
-}\r
-\r
-void idStr::BackSlashesToSlashes\r
-   (\r
-   void\r
-   )\r
-\r
-   {\r
-   int i;\r
-\r
-   EnsureDataWritable ();\r
-\r
-   for ( i=0; i < m_data->len; i++ )\r
-      {\r
-      if ( m_data->data[i] == '\\' )\r
-         m_data->data[i] = '/';\r
-      }\r
-   }\r
-\r
-void idStr::snprintf \r
-   (\r
-   char *dst,\r
-   int size,\r
-   const char *fmt, \r
-   ...\r
-   )\r
-\r
-   {\r
-   char buffer[0x10000];\r
-       int             len;\r
-       va_list         argptr;\r
-\r
-       va_start (argptr,fmt);\r
-       len = vsprintf (buffer,fmt,argptr);\r
-       va_end (argptr);\r
-       \r
-   assert ( len < size );\r
-\r
-   strncpy (dst, buffer, size-1);\r
-   }\r
-\r
-#ifdef _WIN32\r
-#pragma warning(disable : 4189)                // local variable is initialized but not referenced\r
-#endif\r
-\r
-/*\r
-=================\r
-TestStringClass\r
-\r
-This is a fairly rigorous test of the idStr class's functionality.\r
-Because of the fairly global and subtle ramifications of a bug occuring\r
-in this class, it should be run after any changes to the class.\r
-Add more tests as functionality is changed.  Tests should include\r
-any possible bounds violation and NULL data tests.\r
-=================\r
-*/\r
-void TestStringClass\r
-       (\r
-       void \r
-       )\r
-\r
-       {\r
-       char    ch;                                                     // ch == ?\r
-       idStr   *t;                                                     // t == ?\r
-       idStr   a;                                                              // a.len == 0, a.data == "\0"\r
-       idStr   b;                                                              // b.len == 0, b.data == "\0"\r
-       idStr   c( "test" );                            // c.len == 4, c.data == "test\0"\r
-       idStr   d( c );                                         // d.len == 4, d.data == "test\0"\r
-       idStr   e( reinterpret_cast<const char *>(NULL) );                                      \r
-                                 // e.len == 0, e.data == "\0"                                 ASSERT!\r
-       int     i;                                                              // i == ?\r
-\r
-       i = a.length();                                 // i == 0\r
-       i = c.length();                                 // i == 4\r
-\r
-       const char *s1 = a.c_str();     // s1 == "\0"\r
-       const char *s2 = c.c_str();     // s2 == "test\0"\r
-\r
-       t = new idStr();                                                // t->len == 0, t->data == "\0"\r
-       delete t;                                                       // t == ?\r
-\r
-       b = "test";                                                     // b.len == 4, b.data == "test\0"\r
-       t = new idStr( "test" );                        // t->len == 4, t->data == "test\0"\r
-       delete t;                                                       // t == ?\r
-\r
-       a = c;                                                          // a.len == 4, a.data == "test\0"\r
-//   a = "";\r
-   a = NULL;                                                   // a.len == 0, a.data == "\0"                                   ASSERT!\r
-       a = c + d;                                                      // a.len == 8, a.data == "testtest\0"\r
-       a = c + "wow";                                          // a.len == 7, a.data == "testwow\0"\r
-       a = c + reinterpret_cast<const char *>(NULL);\r
-                                 // a.len == 4, a.data == "test\0"                     ASSERT!\r
-       a = "this" + d;                                 // a.len == 8, a.data == "thistest\0"\r
-       a = reinterpret_cast<const char *>(NULL) + d;\r
-                                 // a.len == 4, a.data == "test\0"                     ASSERT!\r
-       a += c;                                                         // a.len == 8, a.data == "testtest\0"\r
-       a += "wow";                                                     // a.len == 11, a.data == "testtestwow\0"\r
-       a += reinterpret_cast<const char *>(NULL);\r
-                                 // a.len == 11, a.data == "testtestwow\0"     ASSERT!\r
-\r
-       a = "test";                                                     // a.len == 4, a.data == "test\0"\r
-       ch = a[ 0 ];                                            // ch == 't'\r
-       ch = a[ -1 ];                                           // ch == 0                                                                                      ASSERT!\r
-       ch = a[ 1000 ];                                 // ch == 0                                                                                      ASSERT!\r
-       ch = a[ 0 ];                                            // ch == 't'\r
-       ch = a[ 1 ];                                            // ch == 'e'\r
-       ch = a[ 2 ];                                            // ch == 's'\r
-       ch = a[ 3 ];                                            // ch == 't'\r
-       ch = a[ 4 ];                                            // ch == '\0'                                                                           ASSERT!\r
-       ch = a[ 5 ];                                            // ch == '\0'                                                                           ASSERT!\r
-\r
-       a[ 1 ] = 'b';                                           // a.len == 4, a.data == "tbst\0"\r
-       a[ -1 ] = 'b';                                          // a.len == 4, a.data == "tbst\0"                       ASSERT!\r
-       a[ 0 ] = '0';                                           // a.len == 4, a.data == "0bst\0"\r
-       a[ 1 ] = '1';                                           // a.len == 4, a.data == "01st\0"\r
-       a[ 2 ] = '2';                                           // a.len == 4, a.data == "012t\0"\r
-       a[ 3 ] = '3';                                           // a.len == 4, a.data == "0123\0"\r
-       a[ 4 ] = '4';                                           // a.len == 4, a.data == "0123\0"                       ASSERT!\r
-       a[ 5 ] = '5';                                           // a.len == 4, a.data == "0123\0"                       ASSERT!\r
-       a[ 7 ] = '7';                                           // a.len == 4, a.data == "0123\0"                       ASSERT!\r
-\r
-       a = "test";                                                     // a.len == 4, a.data == "test\0"\r
-       b = "no";                                                       // b.len == 2, b.data == "no\0"\r
-\r
-       i = ( a == b );                                 // i == 0\r
-       i = ( a == c );                                 // i == 1\r
-\r
-       i = ( a == "blow" );                            // i == 0\r
-       i = ( a == "test" );                            // i == 1\r
-       i = ( a == NULL );                              // i == 0                                                                                       ASSERT!\r
-\r
-       i = ( "test" == b );                            // i == 0\r
-       i = ( "test" == a );                            // i == 1\r
-       i = ( NULL == a );                              // i == 0                                                                                       ASSERT!\r
-\r
-       i = ( a != b );                                 // i == 1\r
-       i = ( a != c );                                 // i == 0\r
-\r
-       i = ( a != "blow" );                            // i == 1\r
-       i = ( a != "test" );                            // i == 0\r
-       i = ( a != NULL );                              // i == 1                                                                                       ASSERT!\r
-\r
-       i = ( "test" != b );                            // i == 1\r
-       i = ( "test" != a );                            // i == 0\r
-       i = ( NULL != a );                              // i == 1                                                                                       ASSERT!\r
-\r
-   a = "test";                   // a.data == "test"\r
-   b = a;                        // b.data == "test"\r
-\r
-   a = "not";                   // a.data == "not", b.data == "test"\r
-\r
-   a = b;                        // a.data == b.data == "test"\r
-\r
-   a += b;                       // a.data == "testtest", b.data = "test"\r
-\r
-   a = b;\r
-\r
-   a[1] = '1';                   // a.data = "t1st", b.data = "test"\r
-       }\r
-\r
-#ifdef _WIN32\r
-#pragma warning(default : 4189)                // local variable is initialized but not referenced\r
-#pragma warning(disable : 4514)     // unreferenced inline function has been removed\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
+
+#include "util_str.h"
+#include <stdlib.h>
+#include <ctype.h>
+#include <stdio.h>
+#include <stdarg.h>
+
+#ifdef _WIN32
+#pragma warning(disable : 4244)     // 'conversion' conversion from 'type1' to 'type2', possible loss of data
+#pragma warning(disable : 4710)     // function 'blah' not inlined
+#endif
+
+static const int STR_ALLOC_GRAN = 20;
+
+// screwy but intentional
+#ifdef __APPLE_BUG__
+char *idStr::__tolower
+#else
+char *idStr::tolower
+#endif
+   (
+   char *s1
+   )
+   
+   {
+   char *s;
+
+   s = s1;
+       while( *s )
+      {
+      *s = ::tolower( *s );
+               s++;
+          }
+   
+   return s1;
+   }
+
+// screwy but intentional
+#ifdef __APPLE_BUG__
+char *idStr::__toupper
+#else
+char *idStr::toupper
+#endif
+   (
+   char *s1
+   )
+   
+   {
+   char *s;
+
+   s = s1;
+       while( *s )
+      {
+      *s = ::toupper( *s );
+               s++;
+          }
+   
+   return s1;
+   }
+
+int idStr::icmpn
+   (
+   const char *s1, 
+   const char *s2, 
+   int n
+   )
+   
+   {
+       int c1;
+   int c2;
+       
+       do 
+      {
+               c1 = *s1++;
+               c2 = *s2++;
+
+               if ( !n-- )
+         {
+         // idStrings are equal until end point
+                       return 0;
+                  }
+               
+               if ( c1 != c2 )
+         {
+                       if ( c1 >= 'a' && c1 <= 'z' )
+            {
+                               c1 -= ( 'a' - 'A' );
+                          }
+
+                       if ( c2 >= 'a' && c2 <= 'z' )
+            {
+                               c2 -= ( 'a' - 'A' );
+                          }
+
+                       if ( c1 < c2 )
+            {
+            // strings less than
+                               return -1;
+                          }
+         else if ( c1 > c2 ) 
+            {
+            // strings greater than
+            return 1;
+            }
+                  }
+          } 
+   while( c1 );
+       
+   // strings are equal
+       return 0;
+   }
+
+int idStr::icmp
+   (
+   const char *s1,
+   const char *s2
+   )
+   
+   {
+       int c1;
+   int c2;
+       
+       do 
+      {
+               c1 = *s1++;
+               c2 = *s2++;
+
+               if ( c1 != c2 )
+         {
+                       if ( c1 >= 'a' && c1 <= 'z' )
+            {
+                               c1 -= ( 'a' - 'A' );
+                          }
+
+                       if ( c2 >= 'a' && c2 <= 'z' )
+            {
+                               c2 -= ( 'a' - 'A' );
+                          }
+
+                       if ( c1 < c2 )
+            {
+            // strings less than
+                               return -1;
+                          }
+         else if ( c1 > c2 ) 
+            {
+            // strings greater than
+            return 1;
+            }
+                  }
+          } 
+   while( c1 );
+       
+   // strings are equal
+       return 0;
+   }
+
+int idStr::cmpn
+   (
+   const char *s1, 
+   const char *s2, 
+   int n
+   )
+   
+   {
+       int c1;
+   int c2;
+       
+       do 
+      {
+               c1 = *s1++;
+               c2 = *s2++;
+
+               if ( !n-- )
+         {
+         // strings are equal until end point
+                       return 0;
+                  }
+               
+               if ( c1 < c2 )
+         {
+         // strings less than
+                       return -1;
+                       }
+      else if ( c1 > c2 ) 
+         {
+         // strings greater than
+         return 1;
+         }
+          } 
+   while( c1 );
+       
+   // strings are equal
+       return 0;
+   }
+
+int idStr::cmp
+   (
+   const char *s1, 
+   const char *s2
+   )
+   
+   {
+       int c1;
+   int c2;
+       
+       do 
+      {
+               c1 = *s1++;
+               c2 = *s2++;
+
+               if ( c1 < c2 )
+         {
+         // strings less than
+                       return -1;
+                       }
+      else if ( c1 > c2 ) 
+         {
+         // strings greater than
+         return 1;
+         }
+          } 
+   while( c1 );
+       
+   // strings are equal
+       return 0;
+   }
+
+/*
+============
+IsNumeric
+
+Checks a string to see if it contains only numerical values.
+============
+*/
+bool idStr::isNumeric
+   (
+   const char *str
+   )
+
+   {
+       int len;
+       int i;
+       bool dot;
+
+       if ( *str == '-' )
+               {
+               str++;
+               }
+
+       dot = false;
+       len = strlen( str );
+       for( i = 0; i < len; i++ )
+               {
+               if ( !isdigit( str[ i ] ) )
+                       {
+                       if ( ( str[ i ] == '.' ) && !dot )
+                               {
+                               dot = true;
+                               continue;
+                               }
+                       return false;
+                       }
+               }
+
+       return true;
+   }
+
+idStr operator+
+   (
+   const idStr& a,
+   const float b
+   )
+
+   {
+   char text[ 20 ];
+
+       idStr result( a );
+
+   sprintf( text, "%f", b );
+       result.append( text );
+
+       return result;
+   }
+
+idStr operator+
+   (
+   const idStr& a,
+   const int b
+   )
+
+   {
+   char text[ 20 ];
+
+       idStr result( a );
+
+   sprintf( text, "%d", b );
+       result.append( text );
+
+       return result;
+   }
+
+idStr operator+
+   (
+   const idStr& a,
+   const unsigned b
+   )
+
+   {
+   char text[ 20 ];
+
+       idStr result( a );
+
+   sprintf( text, "%u", b );
+       result.append( text );
+
+       return result;
+   }
+
+idStr& idStr::operator+=
+       (
+       const float a
+       )
+
+       {
+   char text[ 20 ];
+
+   sprintf( text, "%f", a );
+       append( text );
+
+   return *this;
+       }
+
+idStr& idStr::operator+=
+       (
+       const int a
+       )
+
+       {
+   char text[ 20 ];
+
+   sprintf( text, "%d", a );
+       append( text );
+
+   return *this;
+       }
+
+idStr& idStr::operator+=
+       (
+       const unsigned a
+       )
+
+       {
+   char text[ 20 ];
+
+   sprintf( text, "%u", a );
+       append( text );
+
+   return *this;
+       }
+
+void idStr::CapLength 
+   (
+   int newlen 
+   )
+
+   {
+   assert ( m_data );
+   
+   if ( length() <= newlen )
+      return;
+
+   EnsureDataWritable ();
+
+   m_data->data[newlen] = 0;
+   m_data->len = newlen;
+   }
+
+void idStr::EnsureDataWritable 
+   (
+   void
+   )
+
+   {
+   assert ( m_data );
+   strdata *olddata;
+   int len;
+
+   if ( !m_data->refcount )
+      return;
+
+   olddata = m_data;
+   len = length();
+
+   m_data = new strdata;
+
+   EnsureAlloced ( len + 1, false );
+   strncpy ( m_data->data, olddata->data, len+1 );
+   m_data->len = len;
+
+   olddata->DelRef ();
+   }
+
+void idStr::EnsureAlloced (int amount, bool keepold) {
+
+       if ( !m_data ) {
+      m_data = new strdata();
+       }
+   
+       // Now, let's make sure it's writable
+       EnsureDataWritable ();
+
+       char *newbuffer;
+       bool wasalloced = ( m_data->alloced != 0 );
+
+       if ( amount < m_data->alloced ) {
+               return;
+       }
+
+       assert ( amount );
+       if ( amount == 1 ) {
+               m_data->alloced = 1;
+       } else {
+               int newsize, mod;
+               mod = amount % STR_ALLOC_GRAN;
+               if ( !mod ) {
+                       newsize = amount;
+               } else {
+         newsize = amount + STR_ALLOC_GRAN - mod;
+               }
+               m_data->alloced = newsize;
+       }
+
+       newbuffer = new char[m_data->alloced];
+       if ( wasalloced && keepold ) {
+               strcpy ( newbuffer, m_data->data );
+       }
+
+       if ( m_data->data ) {
+               delete [] m_data->data;
+    }
+       m_data->data = newbuffer;
+}
+
+void idStr::BackSlashesToSlashes
+   (
+   void
+   )
+
+   {
+   int i;
+
+   EnsureDataWritable ();
+
+   for ( i=0; i < m_data->len; i++ )
+      {
+      if ( m_data->data[i] == '\\' )
+         m_data->data[i] = '/';
+      }
+   }
+
+void idStr::snprintf 
+   (
+   char *dst,
+   int size,
+   const char *fmt, 
+   ...
+   )
+
+   {
+   char buffer[0x10000];
+       int             len;
+       va_list         argptr;
+
+       va_start (argptr,fmt);
+       len = vsprintf (buffer,fmt,argptr);
+       va_end (argptr);
+       
+   assert ( len < size );
+
+   strncpy (dst, buffer, size-1);
+   }
+
+#ifdef _WIN32
+#pragma warning(disable : 4189)                // local variable is initialized but not referenced
+#endif
+
+/*
+=================
+TestStringClass
+
+This is a fairly rigorous test of the idStr class's functionality.
+Because of the fairly global and subtle ramifications of a bug occuring
+in this class, it should be run after any changes to the class.
+Add more tests as functionality is changed.  Tests should include
+any possible bounds violation and NULL data tests.
+=================
+*/
+void TestStringClass
+       (
+       void 
+       )
+
+       {
+       char    ch;                                                     // ch == ?
+       idStr   *t;                                                     // t == ?
+       idStr   a;                                                              // a.len == 0, a.data == "\0"
+       idStr   b;                                                              // b.len == 0, b.data == "\0"
+       idStr   c( "test" );                            // c.len == 4, c.data == "test\0"
+       idStr   d( c );                                         // d.len == 4, d.data == "test\0"
+       idStr   e( reinterpret_cast<const char *>(NULL) );                                      
+                                 // e.len == 0, e.data == "\0"                                 ASSERT!
+       int     i;                                                              // i == ?
+
+       i = a.length();                                 // i == 0
+       i = c.length();                                 // i == 4
+
+       const char *s1 = a.c_str();     // s1 == "\0"
+       const char *s2 = c.c_str();     // s2 == "test\0"
+
+       t = new idStr();                                                // t->len == 0, t->data == "\0"
+       delete t;                                                       // t == ?
+
+       b = "test";                                                     // b.len == 4, b.data == "test\0"
+       t = new idStr( "test" );                        // t->len == 4, t->data == "test\0"
+       delete t;                                                       // t == ?
+
+       a = c;                                                          // a.len == 4, a.data == "test\0"
+//   a = "";
+   a = NULL;                                                   // a.len == 0, a.data == "\0"                                   ASSERT!
+       a = c + d;                                                      // a.len == 8, a.data == "testtest\0"
+       a = c + "wow";                                          // a.len == 7, a.data == "testwow\0"
+       a = c + reinterpret_cast<const char *>(NULL);
+                                 // a.len == 4, a.data == "test\0"                     ASSERT!
+       a = "this" + d;                                 // a.len == 8, a.data == "thistest\0"
+       a = reinterpret_cast<const char *>(NULL) + d;
+                                 // a.len == 4, a.data == "test\0"                     ASSERT!
+       a += c;                                                         // a.len == 8, a.data == "testtest\0"
+       a += "wow";                                                     // a.len == 11, a.data == "testtestwow\0"
+       a += reinterpret_cast<const char *>(NULL);
+                                 // a.len == 11, a.data == "testtestwow\0"     ASSERT!
+
+       a = "test";                                                     // a.len == 4, a.data == "test\0"
+       ch = a[ 0 ];                                            // ch == 't'
+       ch = a[ -1 ];                                           // ch == 0                                                                                      ASSERT!
+       ch = a[ 1000 ];                                 // ch == 0                                                                                      ASSERT!
+       ch = a[ 0 ];                                            // ch == 't'
+       ch = a[ 1 ];                                            // ch == 'e'
+       ch = a[ 2 ];                                            // ch == 's'
+       ch = a[ 3 ];                                            // ch == 't'
+       ch = a[ 4 ];                                            // ch == '\0'                                                                           ASSERT!
+       ch = a[ 5 ];                                            // ch == '\0'                                                                           ASSERT!
+
+       a[ 1 ] = 'b';                                           // a.len == 4, a.data == "tbst\0"
+       a[ -1 ] = 'b';                                          // a.len == 4, a.data == "tbst\0"                       ASSERT!
+       a[ 0 ] = '0';                                           // a.len == 4, a.data == "0bst\0"
+       a[ 1 ] = '1';                                           // a.len == 4, a.data == "01st\0"
+       a[ 2 ] = '2';                                           // a.len == 4, a.data == "012t\0"
+       a[ 3 ] = '3';                                           // a.len == 4, a.data == "0123\0"
+       a[ 4 ] = '4';                                           // a.len == 4, a.data == "0123\0"                       ASSERT!
+       a[ 5 ] = '5';                                           // a.len == 4, a.data == "0123\0"                       ASSERT!
+       a[ 7 ] = '7';                                           // a.len == 4, a.data == "0123\0"                       ASSERT!
+
+       a = "test";                                                     // a.len == 4, a.data == "test\0"
+       b = "no";                                                       // b.len == 2, b.data == "no\0"
+
+       i = ( a == b );                                 // i == 0
+       i = ( a == c );                                 // i == 1
+
+       i = ( a == "blow" );                            // i == 0
+       i = ( a == "test" );                            // i == 1
+       i = ( a == NULL );                              // i == 0                                                                                       ASSERT!
+
+       i = ( "test" == b );                            // i == 0
+       i = ( "test" == a );                            // i == 1
+       i = ( NULL == a );                              // i == 0                                                                                       ASSERT!
+
+       i = ( a != b );                                 // i == 1
+       i = ( a != c );                                 // i == 0
+
+       i = ( a != "blow" );                            // i == 1
+       i = ( a != "test" );                            // i == 0
+       i = ( a != NULL );                              // i == 1                                                                                       ASSERT!
+
+       i = ( "test" != b );                            // i == 1
+       i = ( "test" != a );                            // i == 0
+       i = ( NULL != a );                              // i == 1                                                                                       ASSERT!
+
+   a = "test";                   // a.data == "test"
+   b = a;                        // b.data == "test"
+
+   a = "not";                   // a.data == "not", b.data == "test"
+
+   a = b;                        // a.data == b.data == "test"
+
+   a += b;                       // a.data == "testtest", b.data = "test"
+
+   a = b;
+
+   a[1] = '1';                   // a.data = "t1st", b.data = "test"
+       }
+
+#ifdef _WIN32
+#pragma warning(default : 4189)                // local variable is initialized but not referenced
+#pragma warning(disable : 4514)     // unreferenced inline function has been removed
+#endif