/* =========================================================================== maya2q3 - export .md3 files from maya Copyright (C) 2005 HermitWorks Entertainment Corporation This program 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. This program 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 this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. =========================================================================== */ #ifndef INC__string_h_ #define INC__string_h_ #include #include #ifdef _MSC_VER #pragma warning( push ) #pragma warning( disable : 4127 ) //constant conditional --by design #endif #ifndef _MSC_VER #define strnicmp( s1, s2, n ) strncasecmp( s1, s2, n ) #define stricmp( s1, s2 ) strcasecmp( s1, s2 ) #endif //static string class //because I hate strn*** template< size_t n, bool cs = true > class sstr { private: char val[ n ]; public: enum { MaxLength = n, IsCaseSensitive = (cs ? 1 : 0) }; sstr() { val[ 0 ] = '\0'; } sstr( const char *str ) { strncpy( val, str, n - 1 ); val[ n - 1 ] = '\0'; } template< size_t i > sstr( const sstr< i > &src ) { strncpy( val, (const char*)src, min( n - 1, i ) ); val[ n - 1 ] = '\0'; } //n doesn't include tne null template< int i > sstr< i > Substring( size_t start, size_t len = n - 1 ) { sstr< i > ret; if( start + len >= n ) len = n - start - 1; if( len >= i ) len = i - 1; strncpy( ret.val, val + start, len ); ret.val[ len ] = '\0'; return ret; } sstr< n > Substring( size_t start, size_t len = n - 1 ) { return Substring< n >( start, len ); } void Replace( char oldCh, char newCh ) { for( size_t i = 0; i < n && val[ i ]; i++ ) if( val[ i ] == oldCh ) val[ i ] = newCh; } template< size_t i > sstr< n >& operator = ( const sstr< i > &src ) { strncpy( val, src.val, min( n - 1, i ) ); val[ n - 1 ] = '\0'; return *this; } sstr& operator = ( const char *src ) { strncpy( val, src, n - 1 ); val[ n - 1 ] = '\0'; return *this; } operator const char* () const { return val; } operator char* () { return val; } size_t Length() { return strlen( val ); } int LastIndexOf( char c ) { int i = Length() - 1; while( i >= 0 ) { if( val[i] == c ) break; i--; } return i; } bool Append( const char *s, ... ) { va_list argptr; va_start( argptr, s ); size_t lt = Length(); int vsret = vsnprintf( val + lt, n - lt, s, argptr ); val[ n - 1 ] = '\0'; //in case we hit the end va_end( argptr ); return vsret >= 0; //return true if we didn't truncate } int CompareTo( const char *s ) const { if( cs ) return strncmp( val, s, n ); else return strnicmp( val, s, n ); } int CompareTo( const char *s, bool caseSensitive ) const { if( caseSensitive ) return strncmp( val, s, n ); else return strnicmp( val, s, n ); } sstr< n, cs > ToLower( void ) { sstr< n, cs > ret = *this; strlwr( ret.val ); return ret; } sstr< n, cs > ToUpper( void ) { sstr< n, cs > ret = *this; strupr( ret.val ); return ret; } bool BeginsWith( const char *str ) const { for( const char *c = val, *s = str, *end = val + n; c < end; c++, s++ ) { if( !*s ) return true; if( !*c || (cs ? *s : tolower( *s )) != (cs ? *c : tolower( *c )) ) return false; } return false; } #define __sstr_cmp_op( op ) \ \ bool operator op ( const char* s ) const \ { \ return CompareTo( s ) op 0; \ } \ \ template< size_t i, bool cs2 > \ bool operator op ( const sstr< i, cs2 > &s ) const \ { \ return CompareTo( s.val ) op 0; \ } __sstr_cmp_op( == ) __sstr_cmp_op( != ) __sstr_cmp_op( >= ) __sstr_cmp_op( <= ) __sstr_cmp_op( > ) __sstr_cmp_op( < ) #undef __sstr_cmp_op }; //assigning a string to this class copies the string into new memory //string is freed when the destructor is called class dupstr { private: char *str; public: dupstr( char *str ) { dupstr::str = strdup( str ); } ~dupstr( void ) { free( str ); } dupstr & operator = ( const char *str ) { free( dupstr::str ); dupstr::str = strdup( str ); } operator char * ( void ) { return str; } operator const char * ( void ) const { return str; } }; typedef sstr< 1024, false > parse_token; //port of Com_ParseExt void ParseExt( const char *&data_p, bool allowLineBreaks, parse_token &tok ); void SkipRestOfLine( const char *&data ); #ifdef _MSC_VER #pragma warning( pop ) #endif #ifdef PATH_MAX typedef sstr< PATH_MAX > ospath; #else typedef sstr< MAX_PATH > ospath; #endif #endif