00001 /* 00002 00003 ************************************************************************* 00004 00005 ArmageTron -- Just another Tron Lightcycle Game in 3D. 00006 Copyright (C) 2000 Manuel Moos (manuel@moosnet.de) 00007 00008 ************************************************************************** 00009 00010 This program is free software; you can redistribute it and/or 00011 modify it under the terms of the GNU General Public License 00012 as published by the Free Software Foundation; either version 2 00013 of the License, or (at your option) any later version. 00014 00015 This program is distributed in the hope that it will be useful, 00016 but WITHOUT ANY WARRANTY; without even the implied warranty of 00017 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00018 GNU General Public License for more details. 00019 00020 You should have received a copy of the GNU General Public License 00021 along with this program; if not, write to the Free Software 00022 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00023 00024 *************************************************************************** 00025 00026 */ 00027 00028 #include "tMemManager.h" 00029 #include "tString.h" 00030 #include "tLocale.h" 00031 #include "tConfiguration.h" 00032 #include "tException.h" 00033 #include <ctype.h> 00034 #include <string> 00035 #include <iostream> 00036 00037 // ******************************************************************************* 00038 // * 00039 // * Helper functions 00040 // * 00041 // ******************************************************************************* 00042 00043 // reads an escape sequence from a stream 00044 // c: the character just read from the stream 00045 // c2: eventually set to the second character read 00046 // s: the stream to read from 00047 static bool st_ReadEscapeSequence( char & c, char & c2, std::istream & s ) 00048 { 00049 c2 = '\0'; 00050 00051 // detect escaping 00052 if ( c == '\\' && !s.eof() && s.good() ) 00053 { 00054 c2 = s.get(); 00055 00056 // nothing useful read? 00057 if ( s.eof() ) 00058 { 00059 c2 = 0; 00060 return false; 00061 } 00062 00063 // interpret special escape sequences 00064 switch (c2) 00065 { 00066 case 'n': 00067 // turn \n into newline 00068 c = '\n'; 00069 c2 = 0; 00070 return true; 00071 case '"': 00072 case ' ': 00073 case '\'': 00074 case '\n': 00075 // include quoting character as literal 00076 return true; 00077 default: 00078 // take the whole \x sequence as it appeared. 00079 return false; 00080 } 00081 } 00082 00083 return false; 00084 } 00085 00086 // reads an escape sequence from a stream, putting back unread char 00087 // c: the character just read from the stream 00088 // s: the stream to read from 00089 static bool st_ReadEscapeSequence( char & c, std::istream & s ) 00090 { 00091 char c2 = '\0'; 00092 bool ret = st_ReadEscapeSequence( c, c2, s ); 00093 if ( c2 ) 00094 s.putback( c2 ); 00095 return ret; 00096 } 00097 00098 // ******************************************************************************* 00099 // * 00100 // * stream reading operator 00101 // * 00102 // ******************************************************************************* 00109 // ******************************************************************************* 00110 00111 std::istream & operator>> (std::istream &s,tString &x) 00112 { 00113 x.Clear(); 00114 00115 std::ws(s); 00116 00117 char c=s.get(); 00118 00119 // check if the string is quoted 00120 bool quoted = false; 00121 char quoteChar = c; // if it applies, this is the quoting character 00122 if ( c == '"' || c == '\'' ) 00123 { 00124 // yes, it is 00125 quoted = true; 00126 c = s.get(); 00127 } 00128 00129 while((quoted || !( isblank(c) || c == '\n' || c == '\r' ) ) && s.good() && !s.eof()){ 00130 x += c; 00131 c=s.get(); 00132 00133 // read and interpret escape sequences 00134 if ( !st_ReadEscapeSequence( c, s) ) 00135 { 00136 // interpret special characters 00137 if ( quoted && c == quoteChar ) 00138 { 00139 // this marks the end of a quoted string; abort. 00140 c = s.get(); 00141 break; 00142 } 00143 } 00144 else if ( isblank( c ) ) 00145 { 00146 // include escaped spaces 00147 x += c; 00148 c=s.get(); 00149 } 00150 00151 } 00152 s.putback(c); 00153 return s; 00154 } 00155 00156 00157 //removed in favor of searching whole string... 00158 /*void tString::RemoveStartColor(){ 00159 tString oldname = *this; 00160 // unsigned short int colorcodelength = 0; 00161 tString newname = ""; 00162 if (oldname.ge2("0x") == false){ 00163 return; 00164 } 00165 newname.SetLen(14); 00166 // unsigned short int numcounter = 0; 00167 unsigned short int i = 0; 00168 for (i=2; i<oldname.Len(); i++){ 00169 if (oldname(i) > 47 && oldname(i) < 58) { 00170 // std::cout << oldname(i) << std::endl; 00171 colorcodelength++; 00172 } 00173 else { 00174 break; 00175 } 00176 } 00177 unsigned short int c = 0; 00178 for (i=colorcodelength+2; i<oldname.Len(); i++) { 00179 // std::cout << oldname(i); 00180 newname(c) = oldname(i); 00181 c++; 00182 } 00183 for (i=8; i<oldname.Len(); i++) { 00184 // std::cout << oldname(i); 00185 newname(c) = oldname(i); 00186 c++; 00187 } 00188 // std::cout << std::endl << newname << std::endl; 00189 *this = newname; 00190 }*/ 00191 00192 /* 00193 bool tString::operator==(const tString &other) const 00194 { 00195 if (other.Len() != Len()) 00196 return false; 00197 for (int i= Len()-1; i>=0; i--) 00198 if (other(i) != (*this)(i)) 00199 return false; 00200 00201 return true; 00202 } 00203 */ 00204 00205 // Original ge2, didn't compile under linux, some stupid overload or something, so we now have ge2 00206 /*bool tString::operator>=(const tString &other) const 00207 { 00208 if (other.Len() > Len()) { 00209 // std::cout << "lenissue\n"; 00210 return false; 00211 } 00212 for (int i=0; i<other.Len()-1; i++) { 00213 if (other(i) != (*this)(i)) { 00214 // std::cout << "matchissue: '" << other(i) << "' '" << (*this)(i) << "'\n"; 00215 return false; 00216 } 00217 // else { 00218 // std::cout << other(i) << " " << (*this)(i) << std::endl; 00219 // } 00220 } 00221 00222 return true; 00223 } */ 00224 00225 // char st_stringOutputBuffer[tMAX_STRING_OUTPUT]; 00226 00227 // filters illegal characters 00228 class tCharacterFilter 00229 { 00230 public: 00231 tCharacterFilter() 00232 { 00233 int i; 00234 filter[0]=0; 00235 00236 // map all unknown characters to underscores 00237 for (i=255; i>=0; --i) 00238 { 00239 filter[i] = '_'; 00240 } 00241 00242 // leave ASCII characters as they are 00243 // for (i=127; i>=32; --i) 00244 // no, leave all ISO Latin 1 characters as they are 00245 for (i=255; i>=32; --i) 00246 { 00247 filter[i] = i; 00248 } 00249 00250 // map return and tab to space 00251 SetMap('\n',' '); 00252 SetMap('\t',' '); 00253 00255 /* 00256 SetMap(0xc0,0xc5,'A'); 00257 SetMap(0xd1,0xd6,'O'); 00258 SetMap(0xd9,0xdD,'U'); 00259 SetMap(0xdf,'s'); 00260 SetMap(0xe0,0xe5,'a'); 00261 SetMap(0xe8,0xeb,'e'); 00262 SetMap(0xec,0xef,'i'); 00263 SetMap(0xf0,0xf6,'o'); 00264 SetMap(0xf9,0xfc,'u'); 00265 */ 00266 00268 // make this data driven. 00269 } 00270 00271 char Filter( unsigned char in ) 00272 { 00273 return filter[ static_cast< unsigned int >( in )]; 00274 } 00275 private: 00276 void SetMap( int in1, int in2, unsigned char out) 00277 { 00278 tASSERT( in2 <= 0xff ); 00279 tASSERT( 0 <= in1 ); 00280 tASSERT( in1 < in2 ); 00281 for( int i = in2; i >= in1; --i ) 00282 filter[ i ] = out; 00283 } 00284 00285 void SetMap( unsigned char in, unsigned char out) 00286 { 00287 filter[ static_cast< unsigned int >( in ) ] = out; 00288 } 00289 00290 char filter[256]; 00291 }; 00292 00293 // ******************************************************************************* 00294 // * 00295 // * tString 00296 // * 00297 // ******************************************************************************* 00300 // ******************************************************************************* 00301 00302 tString::tString( void ) 00303 { 00304 } 00305 00306 // ******************************************************************************* 00307 // * 00308 // * tString 00309 // * 00310 // ******************************************************************************* 00314 // ******************************************************************************* 00315 00316 tString::tString( BASE const & other ) 00317 : string( other ) 00318 { 00319 } 00320 00321 // ******************************************************************************* 00322 // * 00323 // * tString 00324 // * 00325 // ******************************************************************************* 00329 // ******************************************************************************* 00330 00331 tString::tString( tString const & other ) 00332 : string( other ) 00333 { 00334 } 00335 00336 // ******************************************************************************* 00337 // * 00338 // * tString 00339 // * 00340 // ******************************************************************************* 00344 // ******************************************************************************* 00345 00346 tString::tString( CHAR const * other ) 00347 : string( other ? other : "" ) 00348 { 00349 // tASSERT( other ); 00350 } 00351 00352 // ******************************************************************************* 00353 // * 00354 // * tString 00355 // * 00356 // ******************************************************************************* 00360 // ******************************************************************************* 00361 00362 //tString::tString( tOutput const & other ) 00363 //{ 00364 // operator=( other ); 00365 //} 00366 00367 // ******************************************************************************* 00368 // * 00369 // * operator = 00370 // * 00371 // ******************************************************************************* 00376 // ******************************************************************************* 00377 00378 tString & tString::operator =( tOutput const & other ) 00379 { 00380 Clear(); 00381 *this << other; 00382 return *this; 00383 } 00384 00385 // ******************************************************************************* 00386 // * 00387 // * Size 00388 // * 00389 // ******************************************************************************* 00393 // ******************************************************************************* 00394 00395 tString::size_type tString::Size( void ) const 00396 { 00397 return size(); 00398 } 00399 00400 // ******************************************************************************* 00401 // * 00402 // * ReadLine 00403 // * 00404 // ******************************************************************************* 00409 // ******************************************************************************* 00410 00411 void tString::ReadLine( std::istream & s, bool enableEscapeSequences ) 00412 { 00413 char c=' '; 00414 Clear(); 00415 while(c!='\n' && c!='\r' && isblank(c) && s.good() && !s.eof()){ 00416 c=s.get(); 00417 } 00418 00419 s.putback(c); 00420 c='x'; 00421 00422 while( true ) 00423 { 00424 c=s.get(); 00425 00426 // notice end of line or file 00427 if ( c=='\n' || c=='\r' || !s.good() || s.eof()) 00428 break; 00429 00430 if ( enableEscapeSequences ) 00431 { 00432 char c2 = '\0'; 00433 if ( st_ReadEscapeSequence( c, c2, s ) ) 00434 { 00435 *this += c; 00436 c = 'x'; 00437 continue; 00438 } 00439 else if ( c2 ) 00440 { 00441 *this += c; 00442 *this += c2; 00443 c = 'x'; 00444 continue; 00445 } 00446 } 00447 00448 *this += c; 00449 } 00450 } 00451 00452 // ******************************************************************************* 00453 // * 00454 // * Clear 00455 // * 00456 // ******************************************************************************* 00459 // ******************************************************************************* 00460 00461 void tString::Clear( void ) 00462 { 00463 #ifdef _MSC_VER 00464 *this = ""; 00465 #else 00466 string::clear(); 00467 #endif 00468 } 00469 00470 // ******************************************************************************************* 00471 // * 00472 // * SetPos 00473 // * 00474 // ******************************************************************************************* 00479 // ******************************************************************************************* 00480 00481 void tString::SetPos(int l, bool cut){ 00482 int i; 00483 if ( l < Len() ) 00484 { 00485 if ( cut ) 00486 { 00487 if ( l > 0 ) 00488 { 00489 SetSize( l-1 ); 00490 operator+=(' '); 00491 } 00492 else 00493 { 00494 Clear(); 00495 } 00496 } 00497 else 00498 { 00499 operator+=(' '); 00500 } 00501 } 00502 for(i=Len();i<l;i++) 00503 operator+=(' '); 00504 } 00505 00506 //added by me (Tank Program) 00507 //sees if a string starts with another string 00508 //created for remote admin... 00509 //but used all over the place because it's a cool method --Lucifer 00510 00511 // ******************************************************************************************* 00512 // * 00513 // * StartsWith 00514 // * 00515 // ******************************************************************************************* 00520 // ******************************************************************************************* 00521 00522 bool tString::StartsWith( const tString & other ) const 00523 { 00524 // const tString & rmhxt = *this; 00525 // rmhxt.RemoveHex(); 00526 // *this = rmhxt; 00527 // other.RemoveHex(); 00528 if (other.Len() > Len()) { 00529 return false; 00530 } 00531 for (int i=0; i<other.Len()-1; i++) { 00532 if (other[i] != (*this)[i]) { 00533 return false; 00534 } 00535 } 00536 00537 return true; 00538 } 00539 00540 // ******************************************************************************************* 00541 // * 00542 // * StartsWith 00543 // * 00544 // ******************************************************************************************* 00549 // ******************************************************************************************* 00550 00551 bool tString::StartsWith( const char * other ) const 00552 { 00553 return StartsWith( tString( other ) ); 00554 } 00555 00556 // Added by me (Lucifer) 00557 // Just reverses the two strings and returns StartsWith 00558 // I thought that was clever, but it probably isn't 00559 00560 // ******************************************************************************************* 00561 // * 00562 // * EndsWith 00563 // * 00564 // ******************************************************************************************* 00569 // ******************************************************************************************* 00570 00571 bool tString::EndsWith(const tString & other ) const 00572 { 00573 if (other.Len() > Len()) { 00574 return false; 00575 } 00576 tString thisString = Reverse(); 00577 tString otherString(other); 00578 otherString = otherString.Reverse(); 00579 00580 // Haha, just use StartsWith to do the comparison :) 00581 return thisString.StartsWith(otherString); 00582 //return true; 00583 } 00584 00585 // ******************************************************************************************* 00590 // ******************************************************************************************* 00591 00592 bool tString::EndsWith( const char* other) const { 00593 return EndsWith( tString(other) ); 00594 } 00595 00596 // ******************************************************************************* 00597 // * 00598 // * LTrim 00599 // * 00600 // ******************************************************************************* 00604 // ******************************************************************************* 00605 00606 tString tString::LTrim( void ) const 00607 { 00608 tString toReturn; 00609 bool trim = true; 00610 00611 for( size_t i = 0; i<size(); i++ ) 00612 { 00613 if( !isblank((*this)[i]) ) 00614 trim = false; 00615 if( !trim) 00616 toReturn << (*this)[i]; 00617 } 00618 return toReturn; 00619 } 00620 00621 // ******************************************************************************* 00622 // * 00623 // * RTrim 00624 // * 00625 // ******************************************************************************* 00629 // ******************************************************************************* 00630 00631 tString tString::RTrim( void ) const 00632 { 00633 tString toReturn; 00634 toReturn = Reverse(); 00635 00636 toReturn = toReturn.LTrim(); 00637 return toReturn.Reverse(); 00638 } 00639 00640 // ******************************************************************************* 00641 // * 00642 // * Trim 00643 // * 00644 // ******************************************************************************* 00648 // ******************************************************************************* 00649 00650 tString tString::Trim( void ) const 00651 { 00652 return LTrim().RTrim(); 00653 } 00654 00655 // ******************************************************************************* 00656 // * 00657 // * StrPos 00658 // * 00659 // ******************************************************************************* 00664 // ******************************************************************************* 00665 00666 int tString::StrPos( const tString & tofind ) const 00667 { 00668 if (tofind.Len() > Len()) { 00669 return -1; 00670 } 00671 for (int i=0; i<Len()-1; i++) { 00672 if ((*this)(i) == tofind(0)) { 00673 bool found = true; 00674 for (int j=0; j<tofind.Len()-1; j++) { 00675 if ((*this)(i+j) != tofind(j)) 00676 found = false; 00677 } 00678 if (found == true) 00679 return i; 00680 } 00681 } 00682 00683 return -1; 00684 } 00685 00686 int tString::StrPos( int start, const tString & tofind ) const 00687 { 00688 if (tofind.Len() > Len()) { 00689 return -1; 00690 } 00691 for (int i = start; i<Len()-1; i++) { 00692 if ((*this)(i) == tofind(0)) { 00693 bool found = true; 00694 for (int j=0; j<tofind.Len()-1; j++) { 00695 if ((*this)(i+j) != tofind(j)) 00696 found = false; 00697 } 00698 if (found == true) 00699 return i; 00700 } 00701 } 00702 00703 return -1; 00704 } 00705 00706 // ******************************************************************************* 00707 // * 00708 // * StrPos 00709 // * 00710 // ******************************************************************************* 00715 // ******************************************************************************* 00716 00717 int tString::StrPos( const CHAR * tofind ) const 00718 { 00719 return StrPos( tString ( tofind ) ); 00720 } 00721 00722 int tString::StrPos( int start, const CHAR * tofind ) const 00723 { 00724 return StrPos( start, tString ( tofind ) ); 00725 } 00726 00727 // ******************************************************************************* 00728 // * 00729 // * SubStr 00730 // * 00731 // ******************************************************************************* 00737 // ******************************************************************************* 00738 00739 tString tString::SubStr( const int start, int len ) const 00740 { 00741 tASSERT( start >= 0 ); 00742 00743 if (start > Len()) 00744 return tString(""); 00745 00746 //if len < 0 or too long, take the whole string 00747 if ( (len + start) >= Len() || len < 0) 00748 len = Len() - start - 1; 00749 00750 tString toReturn(""); 00751 00752 for (int i=start; i<(len + start); i++) { 00753 toReturn << (*this)(i); 00754 } 00755 return toReturn; 00756 } 00757 00758 // ******************************************************************************* 00759 // * 00760 // * SubStr 00761 // * 00762 // ******************************************************************************* 00767 // ******************************************************************************* 00768 00769 tString tString::SubStr( const int start ) const 00770 { 00771 return SubStr (start, Len()-start-1 ); 00772 } 00773 00774 // helper for ToInt and ToFloat 00775 template< class T > void ToT( tString const & source, T & target, tString::size_type pos, char const * name ) 00776 { 00777 if ( pos > source.Size() ) 00778 pos = source.Size(); 00779 00780 if ( !source.Convert( target, pos ) ) 00781 { 00782 std::ostringstream message; 00783 00784 if ( pos > 0 ) 00785 { 00786 message << "Expected an " << name << " at position " << pos << " of string \"" << source << "\", but got \"" << static_cast<tString::CHAR const *>(source) + pos << "\"."; 00787 } 00788 else 00789 { 00790 message << "Expected an " << name << ", but got \"" << source << "\"."; 00791 } 00792 throw tGenericException( message.str().c_str(), "Conversion Error" ); 00793 } 00794 } 00795 00796 // ******************************************************************************* 00797 // * 00798 // * ToInt 00799 // * 00800 // ******************************************************************************* 00805 // ******************************************************************************* 00806 00807 int tString::ToInt( size_type pos ) const 00808 { 00809 int ret = 0; 00810 ToT( *this, ret, pos, "integer" ); 00811 return ret; 00812 } 00813 00814 // ******************************************************************************* 00815 // * 00816 // * ToFloat 00817 // * 00818 // ******************************************************************************* 00823 // ******************************************************************************* 00824 00825 REAL tString::ToFloat( size_type pos ) const 00826 { 00827 REAL ret = 0; 00828 ToT( *this, ret, pos, "float" ); 00829 return ret; 00830 } 00831 00832 // exctact the integer at position pos plus 2^16 ( or the character ) [ implementation detail of CompareAlphanumerical ] 00833 static int GetInt( const tString& s, int& pos ) 00834 { 00835 int ret = 0; 00836 int digit = 0; 00837 while ( pos < s.Len() && digit >= 0 && digit <= 9 ) 00838 { 00839 ret = ret*10 + digit; 00840 digit = s[pos] - '0'; 00841 pos++; 00842 } 00843 00844 if ( ret > 0 ) 00845 { 00846 return ret + 0x10000; 00847 } 00848 else 00849 { 00850 return digit + '0'; 00851 } 00852 } 00853 00854 // ******************************************************************************************* 00855 // * 00856 // * CompareAlphaNumerical 00857 // * 00858 // ******************************************************************************************* 00864 // ******************************************************************************************* 00865 00866 int tString::CompareAlphaNumerical( const tString& a, const tString &b) 00867 { 00868 int apos = 0; 00869 int bpos = 0; 00870 00871 while ( apos < a.Len() && bpos < b.Len() ) 00872 { 00873 int adigit = GetInt( a,apos ); 00874 int bdigit = GetInt( b,bpos ); 00875 if ( adigit < bdigit ) 00876 return 1; 00877 else if ( adigit > bdigit ) 00878 return -1; 00879 } 00880 00881 if ( a.Len() - apos < b.Len() - bpos ) 00882 return 1; 00883 else if ( a.Len() - apos > b.Len() - bpos ) 00884 return 1; 00885 else 00886 return 0; 00887 } 00888 00889 // ******************************************************************************************* 00890 // * 00891 // * StripWhitespace 00892 // * 00893 // ******************************************************************************************* 00897 // ******************************************************************************************* 00898 00899 tString tString::StripWhitespace( void ) const 00900 { 00901 tString toReturn; 00902 00903 for( int i = 0; i<=Len()-2; i++ ) 00904 { 00905 if( !isblank((*this)(i)) ) 00906 toReturn << (*this)(i); 00907 } 00908 return toReturn; 00909 } 00910 00912 tString tString::ToLower(void) const { 00913 tString ret(*this); 00914 for(iterator iter=ret.begin(); iter!=ret.end(); ++iter) { 00915 *iter = tolower(*iter); 00916 } 00917 return ret; 00918 } 00919 00921 tString tString::ToUpper(void) const { 00922 tString ret(*this); 00923 for(iterator iter=ret.begin(); iter!=ret.end(); ++iter) { 00924 *iter = toupper(*iter); 00925 } 00926 return ret; 00927 } 00928 00931 int tString::Count(CHAR what) const { 00932 int ret = 0; 00933 for(const_iterator iter=begin(); iter!=end(); ++iter) { 00934 if (*iter == what) 00935 ret++; 00936 } 00937 return ret; 00938 } 00939 00940 //static const char delimiters[] = "`~!@#$%^&*()-=_+[]\\{}|;':\",./<>? "; 00941 static tString delimiters("!?.:;_()-, "); 00942 static tConfItemLine st_wordDelimiters( "WORD_DELIMITERS", delimiters ); 00943 00944 // ******************************************************************************************* 00945 // * 00946 // * PosWordRight 00947 // * 00948 // ******************************************************************************************* 00953 // ******************************************************************************************* 00954 00955 int tString::PosWordRight( int start ) const { 00956 int nextDelimiter = strcspn( SubStr( start, Len() ), delimiters ); 00957 int toMove = nextDelimiter; 00958 00959 // A delimter in our immediate path 00960 if ( toMove == 0 ) { 00961 // Move over delimiters 00962 while ( nextDelimiter == 0 && start + 1 < Len() ) { 00963 toMove++; 00964 start++; 00965 nextDelimiter = strcspn( SubStr( start, Len() ), delimiters ); 00966 } 00967 // Skip over the word if not multiple delimiters 00968 if ( toMove == 1 ) { 00969 toMove += nextDelimiter; 00970 } 00971 } 00972 00973 return toMove; 00974 } 00975 00976 // ******************************************************************************************* 00977 // * 00978 // * PosWordLeft 00979 // * 00980 // ******************************************************************************************* 00985 // ******************************************************************************************* 00986 00987 int tString::PosWordLeft( int start ) const { 00988 return -1 * Reverse().PosWordRight( Len() - start - 1 ); 00989 } 00990 00991 // ******************************************************************************************* 00992 // * 00993 // * RemoveWordRight 00994 // * 00995 // ******************************************************************************************* 01002 // ******************************************************************************************* 01003 01004 int tString::RemoveWordRight( int start ) { 01005 int removed = PosWordRight( start ); 01006 RemoveSubStr( start, removed ); 01007 return removed; 01008 } 01009 01010 // ******************************************************************************************* 01011 // * 01012 // * RemoveWordLeft 01013 // * 01014 // ******************************************************************************************* 01021 // ******************************************************************************************* 01022 01023 int tString::RemoveWordLeft( int start ) { 01024 int removed = PosWordLeft( start ); 01025 RemoveSubStr( start, removed ); 01026 return removed; 01027 } 01028 01029 // ******************************************************************************************* 01030 // * 01031 // * RemoveSubStr 01032 // * 01033 // ******************************************************************************************* 01040 // ******************************************************************************************* 01041 01042 void tString::RemoveSubStr( int start, int length ) { 01043 int strLen = Len()-1; 01044 if ( length < 0 ) { 01045 start += length; 01046 length = abs( length ); 01047 } 01048 01049 if ( start + length > strLen || start < 0 || length == 0 ) { 01050 return; 01051 } 01052 01053 if ( start == 0 ) { 01054 if ( strLen - length == 0 ) { 01055 *this = (""); 01056 } 01057 else { 01058 *this = SubStr( start + length, strLen ); 01059 } 01060 } 01061 else { 01062 *this = SubStr( 0, start ) + SubStr( start + length, strLen ); 01063 } 01064 01065 // SetSze(strLen+1-length); 01066 } 01067 01068 01069 // ******************************************************************************************* 01070 // * 01071 // * GetFileMimeExtension 01072 // * 01073 // ******************************************************************************************* 01078 // ******************************************************************************************* 01079 01080 tString tString::GetFileMimeExtension() const { 01081 tString extension; 01082 int currentPosition = Len(); 01083 01084 bool goonie = true; 01085 01086 if( currentPosition < 2 ) return tString(""); 01087 01088 while(goonie) { 01089 extension += SubStr(currentPosition,1); 01090 if( SubStr(currentPosition,1) == "." ) goonie = false; 01091 currentPosition--; 01092 } 01093 01094 extension = extension.Reverse(); 01095 if( extension == (*this) ) return tString(""); 01096 01097 for(size_t i=0; i<extension.size(); i++) 01098 extension[i] = tolower(extension[i]); 01099 return extension; 01100 } 01101 01102 // ******************************************************************************************* 01103 // * 01104 // * Reverse 01105 // * 01106 // ******************************************************************************************* 01110 // ******************************************************************************************* 01111 01112 tString tString::Reverse() const { 01113 tString reversed; 01114 for ( int index = Len() - 2; index >= 0; index-- ) { 01115 reversed << ( *this ) ( index ); 01116 } 01117 01118 return reversed; 01119 } 01120 01121 // ******************************************************************************************* 01122 // * 01123 // * Truncate 01124 // * 01125 // ******************************************************************************************* 01132 // ******************************************************************************************* 01133 01134 tString tString::Truncate( int truncateAt ) const 01135 { 01136 // The string does not need to be truncated 01137 if ( truncateAt >= Len() ) 01138 return *this; 01139 01140 return SubStr( 0, truncateAt ) + "..."; 01141 } 01142 01143 // ******************************************************************************* 01144 // * 01145 // * operator [] 01146 // * 01147 // ******************************************************************************* 01152 // ******************************************************************************* 01153 01154 tString::CHAR tString::operator []( size_t i ) const 01155 { 01156 tASSERT( i <= size() ); 01157 return BASE::operator[]( i ); 01158 } 01159 01160 // ******************************************************************************* 01161 // * 01162 // * operator [] 01163 // * 01164 // ******************************************************************************* 01169 // ******************************************************************************* 01170 01171 tString::CHAR & tString::operator []( size_t i ) 01172 { 01173 while( i >= size() ) 01174 { 01175 *this += ' '; 01176 #ifdef DEBUG 01177 static bool warn = true; 01178 if( warn ) 01179 { 01180 warn = false; 01181 tERR_MESSAGE("Auto-expanding string, this functionality will go away."); 01182 } 01183 #endif 01184 } 01185 01186 return BASE::operator[](i); 01187 } 01188 01189 // ******************************************************************************* 01190 // * 01191 // * operator [] 01192 // * 01193 // ******************************************************************************* 01198 // ******************************************************************************* 01199 01200 tString::CHAR tString::operator []( int i ) const 01201 { 01202 return operator[]( size_t(i) ); 01203 } 01204 01205 // ******************************************************************************* 01206 // * 01207 // * operator [] 01208 // * 01209 // ******************************************************************************* 01214 // ******************************************************************************* 01215 01216 tString::CHAR & tString::operator []( int i ) 01217 { 01218 return operator[]( size_t(i) ); 01219 } 01220 01221 // ******************************************************************************* 01222 // * 01223 // * operator ( ) 01224 // * 01225 // ******************************************************************************* 01230 // ******************************************************************************* 01231 01232 tString::CHAR tString::operator ()( size_t i ) const 01233 { 01234 tASSERT( i <= size() ); 01235 return BASE::operator[]( i ); 01236 } 01237 01238 // ******************************************************************************* 01239 // * 01240 // * operator ( ) 01241 // * 01242 // ******************************************************************************* 01247 // ******************************************************************************* 01248 01249 tString::CHAR & tString::operator ()( size_t i ) 01250 { 01251 tASSERT( i < size() ); 01252 return BASE::operator[]( i ); 01253 } 01254 01255 // ******************************************************************************* 01256 // * 01257 // * operator [] 01258 // * 01259 // ******************************************************************************* 01264 // ******************************************************************************* 01265 01266 tString::CHAR tString::operator ()( int i ) const 01267 { 01268 return operator()( size_t(i) ); 01269 } 01270 01271 // ******************************************************************************* 01272 // * 01273 // * operator () 01274 // * 01275 // ******************************************************************************* 01280 // ******************************************************************************* 01281 01282 tString::CHAR & tString::operator ()( int i ) 01283 { 01284 return operator()( size_t(i) ); 01285 } 01286 01287 // ******************************************************************************************* 01288 // * 01289 // * Compare 01290 // * 01291 // ******************************************************************************************* 01297 // ******************************************************************************************* 01298 01299 int tString::Compare( const char* other, bool ignoreCase ) const 01300 { 01301 if ( ignoreCase ) { 01302 return strcasecmp( *this, other ); 01303 } 01304 else { 01305 return Compare( other ); 01306 } 01307 } 01308 01309 // ******************************************************************************************* 01310 // * 01311 // * Compare 01312 // * 01313 // ******************************************************************************************* 01318 // ******************************************************************************************* 01319 01320 int tString::Compare( const char* other ) const 01321 { 01322 if ( !other ) 01323 return 1; 01324 01325 return strcmp( *this, other ); 01326 } 01327 01328 // ******************************************************************************* 01329 // * 01330 // * operator const CHAR* 01331 // * 01332 // ******************************************************************************* 01336 // ******************************************************************************* 01337 01338 tString::operator const tString::CHAR *( void ) const 01339 { 01340 return c_str(); 01341 } 01342 01343 // ******************************************************************************* 01344 // * 01345 // * Len 01346 // * 01347 // ******************************************************************************* 01351 // ******************************************************************************* 01352 01353 int tString::Len( void ) const 01354 { 01355 return size() + 1; 01356 } 01357 01359 int tString::LongestLine( void ) const { 01360 unsigned longest = 0; 01361 unsigned pos = 0; 01362 int l; 01363 while ((l=find_first_of('\n', pos)) != -1) { 01364 if(l-pos > longest) 01365 longest = l-pos; 01366 pos = l+1; 01367 } 01368 if(size() - pos > longest) 01369 longest = size() - pos; 01370 return longest; 01371 } 01372 01374 int tColoredString::LongestLine( void ) const { 01375 return tColoredString::RemoveColors(c_str()).LongestLine(); 01376 } 01377 01378 // ******************************************************************************* 01379 // * 01380 // * SetSize 01381 // * 01382 // ******************************************************************************* 01386 // ******************************************************************************* 01387 01388 void tString::SetSize( unsigned int len ) 01389 { 01390 tASSERT(len < 268435456); 01391 01392 while ( len > size() ) 01393 *this += ' '; 01394 if ( len < size() ) 01395 *this = SubStr( 0, len ); 01396 01397 tASSERT( size() == len ); 01398 } 01399 01400 // ******************************************************************************* 01401 // * 01402 // * SetLen 01403 // * 01404 // ******************************************************************************* 01409 // ******************************************************************************* 01410 01411 void tString::SetLen( int len ) 01412 { 01413 // legacy function, don't use 01414 st_Breakpoint(); 01415 01416 while ( len > Len() ) 01417 *this += ' '; 01418 if ( len < Len() ) 01419 *this = SubStr( 0, len ); 01420 01421 tASSERT( Len() == len ); 01422 } 01423 01424 // ******************************************************************************************* 01425 // ******************************************************************************************* 01426 // ******************************************************************************************* 01427 01428 // ******************************************************************************************* 01429 // * 01430 // * ~tColoredString 01431 // * 01432 // ******************************************************************************************* 01435 // ******************************************************************************************* 01436 01437 tColoredString::~tColoredString( void ) 01438 { 01439 } 01440 01441 // ******************************************************************************************* 01442 // * 01443 // * tColoredString 01444 // * 01445 // ******************************************************************************************* 01448 // ******************************************************************************************* 01449 01450 tColoredString::tColoredString( void ) 01451 { 01452 } 01453 01454 // ******************************************************************************************* 01455 // * 01456 // * tColoredString 01457 // * 01458 // ******************************************************************************************* 01462 // ******************************************************************************************* 01463 01464 tColoredString::tColoredString( const tColoredString & other ) 01465 :tString( other ) 01466 { 01467 } 01468 01469 // ******************************************************************************************* 01470 // * 01471 // * tColoredString 01472 // * 01473 // ******************************************************************************************* 01477 // ******************************************************************************************* 01478 01479 tColoredString::tColoredString( const tString & other ) 01480 :tString( other ) 01481 { 01482 } 01483 01484 // ******************************************************************************************* 01485 // * 01486 // * tColoredString 01487 // * 01488 // ******************************************************************************************* 01492 // ******************************************************************************************* 01493 01494 tColoredString::tColoredString( const char * other ) 01495 :tString( other ) 01496 { 01497 } 01498 01499 // ******************************************************************************************* 01500 // * 01501 // * tColoredString 01502 // * 01503 // ******************************************************************************************* 01507 // ******************************************************************************************* 01508 01509 tColoredString::tColoredString( const tOutput & other ) 01510 :tString( other ) 01511 { 01512 } 01513 01514 // ******************************************************************************************* 01515 // * 01516 // * RemoveColors 01517 // * 01518 // ******************************************************************************************* 01523 // ******************************************************************************************* 01524 01525 tString tColoredString::RemoveColors( const char * c ) 01526 { 01527 tString ret; 01528 01529 int len = strlen(c); 01530 01531 bool removed = false; 01532 01533 // walk through string 01534 while (*c!='\0'){ 01535 // skip color codes 01536 if (*c=='0' && len >= 2 && c[1]=='x') 01537 { 01538 if(len >= 8) 01539 { 01540 c += 8; 01541 len -= 8; 01542 removed = true; 01543 } 01544 else 01545 { 01546 // skip incomplete color codes, too 01547 return RemoveColors( ret ); 01548 } 01549 } 01550 else 01551 { 01552 ret << (*(c++)); 01553 len--; 01554 } 01555 } 01556 01557 return removed ? RemoveColors( ret ) : ret; 01558 } 01559 01560 // helper function: removes trailing color of string and returns number of chars 01561 // used by color codes 01562 static int RemoveTrailingColor( tString& s, int maxLen=-1 ) 01563 { 01564 // count bytes lost to color codes 01565 int posDisplacement = 0; 01566 int len = 0; 01567 01568 // walk through string 01569 for ( size_t g=0; g+1 < s.Size(); g++) 01570 { 01571 if (s(g) == '0' && s(g+1) == 'x') 01572 { 01573 // test if the code is legal ( not so far at the end that it overlaps ) 01574 if ( s.Size() >= g + 8 ) 01575 { 01576 // everything is in order, record color code usage and advance 01577 posDisplacement+=8; 01578 g+=7; 01579 } 01580 else 01581 { 01582 // illegal code! Remove it. 01583 s.SetSize( g ); 01584 // s[g]=0; 01585 } 01586 } 01587 else if ( maxLen > 0 ) 01588 { 01589 if ( ++len >= maxLen ) 01590 { 01591 // maximal end reached, cut it off 01592 s.SetSize( g-1 ); 01593 // s[g]=0; 01594 } 01595 } 01596 } 01597 01598 return posDisplacement; 01599 } 01600 01601 // ******************************************************************************************* 01602 // * 01603 // * SetPos 01604 // * 01605 // ******************************************************************************************* 01610 // ******************************************************************************************* 01611 01612 01613 void tColoredString::SetPos( int len, bool cut ) 01614 { 01615 // determine desired raw length taking color codes into account and possibly cutting 01616 int wishLen = len + ::RemoveTrailingColor( *this, cut ? len : -1 ); 01617 01618 // delegate 01619 tString::SetPos( wishLen, cut ); 01620 } 01621 01622 // ******************************************************************************************* 01623 // * 01624 // * RemoveTrailingColor 01625 // * 01626 // ******************************************************************************************* 01629 // ******************************************************************************************* 01630 01631 void tColoredString::RemoveTrailingColor( void ) 01632 { 01633 // delegage 01634 ::RemoveTrailingColor( *this ); 01635 } 01636 01637 // ******************************************************************************************* 01638 // * 01639 // * NetFilter 01640 // * 01641 // ******************************************************************************************* 01644 // ******************************************************************************************* 01645 01646 void tString::NetFilter( void ) 01647 { 01648 static tCharacterFilter filter; 01649 01650 // run through string 01651 for( int i = Len()-2; i>=0; --i ) 01652 { 01653 // character to filter 01654 char & my = (*this)(i); 01655 01656 my = filter.Filter(my); 01657 } 01658 } 01659 01660 bool st_colorStrings=true; 01661 01662 static tConfItem<bool> cs("COLOR_STRINGS",st_colorStrings); 01663 01664 static int RTC(REAL x){ 01665 int ret=int(x*255); 01666 if (ret<0) 01667 ret=0; 01668 if (ret>255) 01669 ret=255; 01670 return ret; 01671 } 01672 01673 static char hex_array[]="0123456789abcdef"; 01674 01675 static char int_to_hex(int i){ 01676 if (i<0 || i >15) 01677 return 'Q'; 01678 else 01679 return hex_array[i]; 01680 } 01681 01682 // ******************************************************************************* 01683 // * 01684 // * color code streaming 01685 // * 01686 // ******************************************************************************* 01692 // ******************************************************************************* 01693 01694 tColoredString & operator <<(tColoredString &s, const tColoredStringProxy &colorCode ) 01695 { 01696 if (st_colorStrings) 01697 { 01698 char cs[9]; 01699 cs[0]='0'; 01700 cs[1]='x'; 01701 01702 int RGB[3]; 01703 RGB[0]=RTC(colorCode.r_); 01704 RGB[1]=RTC(colorCode.g_); 01705 RGB[2]=RTC(colorCode.b_); 01706 01707 for(int i=0;i<3;i++){ 01708 int lp=RGB[i]%16; 01709 int hp=(RGB[i]-lp)/16; 01710 cs[2+2*i]=int_to_hex(hp); 01711 cs[2+2*i+1]=int_to_hex(lp); 01712 } 01713 cs[8]=0; 01714 01715 s << cs; 01716 } 01717 01718 return s; 01719 } 01720 01721 #ifdef _MSC_VER 01722 // non-template replacements for VisualC 01723 bool tString::Convert( int & target, size_type startPos ) const 01724 { 01725 // generate string stream and advance it to the start position 01726 std::istringstream s(*this); 01727 s.seekg(startPos); 01728 01729 // read it 01730 s >> target; 01731 01732 // return failure condition 01733 return !s.fail() && s.eof() || isblank(s.get()); 01734 } 01735 01736 bool tString::Convert( REAL & target, size_type startPos ) const 01737 { 01738 // generate string stream and advance it to the start position 01739 std::istringstream s(*this); 01740 s.seekg(startPos); 01741 01742 // read it 01743 s >> target; 01744 01745 // return failure condition 01746 return !s.fail() && s.eof() || isblank(s.get()); 01747 } 01748 01749 #endif 01750 01751 // ******************************************************************************* 01752 // * 01753 // * Scrapyard 01754 // * 01755 // ******************************************************************************* 01756 01757 /* 01758 tString & tString::operator<<(const char *c){ 01759 return operator+=(c); 01760 } 01761 01762 tString & tString::operator+=(const char *c){ 01763 if (c){ 01764 if ( Len() == 0 ) 01765 operator[](0)='\0'; 01766 01767 int i=Len()-1; 01768 if (i<0) i=0; 01769 while (*c!='\0'){ 01770 operator[](i)=*c; 01771 i++; 01772 c++; 01773 } 01774 operator[](i)='\0'; 01775 } 01776 return *this; 01777 } 01778 01779 tString & tString::operator=(const char *c){ 01780 Clear(); 01781 return operator+=(c); 01782 } 01783 01784 tString tString::operator+(const char *c) const{ 01785 tString s(*this); 01786 return s+=c; 01787 //return s; 01788 } 01789 01790 tString::operator const char *() const{ 01791 if (Len()) 01792 return &operator()(0); 01793 else 01794 return ""; 01795 } 01796 01797 tString & tString::operator<<(char c){ 01798 return operator+=(c); 01799 } 01800 01801 tString & tString::operator+=(char c){ 01802 if ( Len() == 0 ) 01803 operator[](0)='\0'; 01804 01805 int i=Len(); 01806 if (i<=0) i=1; 01807 operator[](i-1)=c; 01808 operator[](i)='\0'; 01809 return *this; 01810 } 01811 01812 tString tString::operator+(char c) const{ 01813 tString s(*this); 01814 return s+=c; 01815 //return s; 01816 } 01817 01818 01819 std::ostream & operator<< (std::ostream &s,const tString &x){ 01820 if(x.Len()) 01821 return s << &(x(0)); 01822 else 01823 return s; 01824 } 01825 01826 void operator <<(tString &s,const char * c){ 01827 std::stringstream S(st_stringOutputBuffer,tMAX_STRING_OUTPUT-1); 01828 S << c << '\0'; 01829 s+=st_stringOutputBuffer; 01830 } 01831 01832 void operator <<(tString &s,const unsigned char * c){ 01833 std::stringstream S(st_stringOutputBuffer,tMAX_STRING_OUTPUT-1); 01834 S << c << '\0'; 01835 s+=st_stringOutputBuffer; 01836 } 01837 01838 void operator <<(tString &s,int c){ 01839 std::stringstream S(st_stringOutputBuffer,tMAX_STRING_OUTPUT-1); 01840 S << c << '\0'; 01841 s+=st_stringOutputBuffer; 01842 } 01843 01844 void operator <<(tString &s,float c){ 01845 std::stringstream S(st_stringOutputBuffer,tMAX_STRING_OUTPUT-1); 01846 S << c << '\0'; 01847 s+=st_stringOutputBuffer; 01848 } 01849 */ 01850 01851 01852 std::stringstream& operator<<(std::stringstream& s,const tString &t) 01853 { 01854 static_cast<std::ostream&>(s) << static_cast<const char *>(t); 01855 return s; 01856 } 01857 01858 /* 01859 std::stringstream& operator<<(std::stringstream& s, const int &t) 01860 { 01861 static_cast<std::ostream&>(s) << static_cast<int >(t); 01862 return s; 01863 } 01864 01865 std::stringstream& operator<<(std::stringstream& s, const float &t) 01866 { 01867 static_cast<std::ostream&>(s) << static_cast<float>(t); 01868 return s; 01869 } 01870 01871 std::stringstream& operator<<(std::stringstream& s, const short unsigned int &t) 01872 { 01873 static_cast<std::ostream&>(s) << static_cast<int>(t); 01874 return s; 01875 } 01876 01877 std::stringstream& operator<<(std::stringstream& s, const short int &t) 01878 { 01879 static_cast<std::ostream&>(s) << static_cast<int>(t); 01880 return s; 01881 } 01882 01883 std::stringstream& operator<<(std::stringstream& s, const unsigned int &t) 01884 { 01885 static_cast<std::ostream&>(s) << static_cast<int>(t); 01886 return s; 01887 } 01888 01889 std::stringstream& operator<<(std::stringstream& s, const unsigned long &t) 01890 { 01891 static_cast<std::ostream&>(s) << static_cast<int>(t); 01892 return s; 01893 } 01894 01895 std::stringstream& operator<<(std::stringstream& s, char t) 01896 { 01897 static_cast<std::ostream&>(s) << t; 01898 return s; 01899 } 01900 01901 std::stringstream& operator<<(std::stringstream& s, bool t) 01902 { 01903 static_cast<std::ostream&>(s) << static_cast<int>(t); 01904 return s; 01905 } 01906 01907 01908 std::stringstream& operator<<(std::stringstream& s, const char * const &t) 01909 { 01910 static_cast<std::ostream&>(s) << static_cast<const char *>(t); 01911 return s; 01912 } 01913 01914 01915 tString & tString::operator=(const tString &s) 01916 { 01917 // self copying is unsafe 01918 if ( &s == this ) 01919 return *this; 01920 01921 Clear(); 01922 for (int i = s.Len()-1; i>=0; i--) 01923 operator[](i) = s(i); 01924 01925 tASSERT( (*this) == s ); 01926 01927 return *this; 01928 } 01929 01930 */ 01931 01932 /* 01933 01934 //static char* st_TempString = NULL; 01935 #ifdef DEBUG 01936 //static int st_TempStringLength = 10; 01937 #else 01938 //static int st_TempStringLength = 1000; 01939 #endif 01940 01941 // static int 01942 01943 class tTempStringCleanup 01944 { 01945 public: 01946 ~tTempStringCleanup() 01947 { 01948 if (st_TempString) 01949 free( st_TempString ); 01950 01951 st_TempString = NULL; 01952 } 01953 }; 01954 01955 static tTempStringCleanup cleanup; 01956 01957 char * tString::ReserveTempString() 01958 { 01959 if (!st_TempString) 01960 st_TempString = reinterpret_cast<char*>( malloc(st_TempStringLength) ); 01961 01962 st_TempString[st_TempStringLength-1] = 0; 01963 st_TempString[st_TempStringLength-2] = 0; 01964 01965 return st_TempString; 01966 } 01967 01968 01969 int tString::TempStringLength() 01970 { 01971 return st_TempStringLength; 01972 } 01973 01974 void tString::MakeTempStringLonger() 01975 { 01976 free(st_TempString); 01977 st_TempString = NULL; 01978 st_TempStringLength *= 2; 01979 } 01980 01981 // ******************************************************************************************* 01982 // * 01983 // * operator == 01984 // * 01985 // ******************************************************************************************* 01990 // ******************************************************************************************* 01991 01992 bool tString::operator ==( const char* other ) const 01993 { 01994 return Compare( other ) == 0; 01995 } 01996 01997 // ******************************************************************************************* 01998 // * 01999 // * operator != 02000 // * 02001 // ******************************************************************************************* 02006 // ******************************************************************************************* 02007 02008 bool tString::operator !=( const char* other ) const 02009 { 02010 return Compare( other ) != 0; 02011 } 02012 02013 // ******************************************************************************************* 02014 // * 02015 // * operator < 02016 // * 02017 // ******************************************************************************************* 02022 // ******************************************************************************************* 02023 02024 bool tString::operator <( const char* other ) const 02025 { 02026 return Compare( other ) < 0; 02027 } 02028 02029 // ******************************************************************************************* 02030 // * 02031 // * operator> 02032 // * 02033 // ******************************************************************************************* 02038 // ******************************************************************************************* 02039 02040 bool tString::operator>( const char* other ) const 02041 { 02042 return Compare( other ) > 0; 02043 } 02044 02045 // ******************************************************************************************* 02046 // * 02047 // * operator <= 02048 // * 02049 // ******************************************************************************************* 02054 // ******************************************************************************************* 02055 02056 bool tString::operator <=( const char* other ) const 02057 { 02058 return Compare( other ) <= 0; 02059 } 02060 02061 // ******************************************************************************************* 02062 // * 02063 // * operator >= 02064 // * 02065 // ******************************************************************************************* 02070 // ******************************************************************************************* 02071 02072 bool tString::operator >=( const char* other ) const 02073 { 02074 return Compare( other ) >= 0; 02075 } 02076 02077 bool operator==( const char* first, const tString& second ) 02078 { 02079 return second == first; 02080 } 02081 02082 bool operator!=( const char* first, const tString& second ) 02083 { 02084 return second != first; 02085 } 02086 02087 bool operator<( const char* first, const tString& second ) 02088 { 02089 return second > first; 02090 } 02091 02092 bool operator>( const char* first, const tString& second ) 02093 { 02094 return second < first; 02095 } 02096 02097 bool operator<=( const char* first, const tString& second ) 02098 { 02099 return second >= first; 02100 } 02101 02102 bool operator>=( const char* first, const tString& second ) 02103 { 02104 return second <= first; 02105 } 02106 02107 bool operator==( const tString& first, const tString& second ) 02108 { 02109 return first.operator==( second ); 02110 } 02111 02112 bool operator!=( const tString& first, const tString& second ) 02113 { 02114 return first.operator!=( second ); 02115 } 02116 02117 bool operator<( const tString& first, const tString& second ) 02118 { 02119 return first.operator<( second ); 02120 } 02121 02122 bool operator>( const tString& first, const tString& second ) 02123 { 02124 return first.operator>( second ); 02125 } 02126 02127 bool operator<=( const tString& first, const tString& second ) 02128 { 02129 return first.operator<=( second ); 02130 } 02131 02132 bool operator>=( const tString& first, const tString& second ) 02133 { 02134 return first.operator>=( second ); 02135 } 02136 02137 void testconversion() 02138 { 02139 float x; 02140 tString t("1"); 02141 tVERIFY( t.Convert( x ) ); 02142 t = "1.2 b s"; 02143 tVERIFY( t.Convert( x ) ); 02144 t = "bla"; 02145 tVERIFY( !t.Convert( x ) ); 02146 t = "1b"; 02147 tVERIFY( !t.Convert( x ) ); 02148 } 02149 */ 02150 02151 02152 // ******************************************************************************************* 02153 // * 02154 // * tIsInList 02155 // * 02156 // ******************************************************************************************* 02164 // ******************************************************************************************* 02166 bool tIsInList( tString const & list_, tString const & item ) 02167 { 02168 tString list = list_; 02169 02170 while( list != "" ) 02171 { 02172 // find the item 02173 int pos = list.StrPos( item ); 02174 02175 // no traditional match? shoot. 02176 if ( pos < 0 ) 02177 { 02178 return false; 02179 } 02180 02181 // check whether the match is a true list match 02182 if ( 02183 ( pos == 0 || list[pos-1] == ',' || isblank(list[pos-1]) ) 02184 && 02185 ( pos + item.Len() >= list.Len() || list[pos+item.Len()-1] == ',' || isblank(list[pos+item.Len()-1]) ) 02186 ) 02187 { 02188 return true; 02189 } 02190 else 02191 { 02192 // no? truncate the list and go on. 02193 list = list.SubStr( pos + 1 ); 02194 } 02195 } 02196 02197 return false; 02198 } 02199 02200 // ********************************************************************** 02201 // * 02202 // * tToLower 02203 // * 02204 // ********************************************************************** 02208 // ********************************************************************** 02209 void tToLower( tString & toTransform ) 02210 { 02211 for( int i = toTransform.Len()-2; i >= 0; --i ) 02212 { 02213 toTransform[i] = tolower( toTransform[i] ); 02214 } 02215 } 02216 02217 // ********************************************************************** 02218 // * 02219 // * tToUpper 02220 // * 02221 // ********************************************************************** 02225 // ********************************************************************** 02226 void tToUpper( tString & toTransform ) 02227 { 02228 for( int i = toTransform.Len()-2; i >= 0; --i ) 02229 { 02230 toTransform[i] = toupper( toTransform[i] ); 02231 } 02232 }