Subversion Repositories spk

Rev

Rev 188 | Rev 285 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed

ÿþ#include "String.h"



#include <sstream>

#include <stdarg.h>

#include <algorithm>

#include <iomanip>

#include <locale>

#include <codecvt>



#include "WString.h"



namespace Utils {



       std::wstring s2ws(const std::string& str)

       {

              try {

                     using convert_typeX = std::codecvt_utf8<wchar_t>;

                     std::wstring_convert<convert_typeX, wchar_t> converterX;



                     return converterX.from_bytes(str);

              }

              catch(std::exception)

              {



              }

              return std::wstring(L"");

       }



       std::string ws2s(const std::wstring& wstr)

       {

              using convert_typeX = std::codecvt_utf8<wchar_t>;

              std::wstring_convert<convert_typeX, wchar_t> converterX;



              return converterX.to_bytes(wstr);

       }





       SString operator+(const char* str1, const SString& str2)

       {

              return SString(str1) + str2;

       }

       SString operator+(const unsigned char* str1, const SString& str2)

       {

              return SString(str1) + str2;

       }



SString::SString(void)                                      { this->assign(""); }

SString::SString(const char *str)                   { this->assign(str); }

SString::SString(const unsigned char *str)   { this->assign((const char *)str); }

SString::SString(const std::string &str)       { this->assign(str);}

SString::SString(const unsigned char c)        { this->assign(1, c); }

SString::SString(const char c)                        { this->assign(1, c); }

SString::SString(const SString &str)              { this->assign(str); }

SString::SString(long l)                                   { this->fromLong(l); }

SString::SString(unsigned long l)                   { this->fromLong((long)l); }

SString::SString(float f)                                 { this->fromFloat(f); }

SString::SString(double f)                               { this->fromDouble(f); }



SString::~SString(void)

{

}



SString SString::PadNumber(long iNumber, int iAmount)

{

       SString str(iNumber);

       return str.padNumber(iAmount);

}



const SString &SString::padNumber(int iAmount)

{

       return this->pad(iAmount, '0');

}



const SString &SString::pad(int iAmount, char cWith)

{

       std::stringstream strm;

       strm << std::setw(iAmount) << std::setfill(cWith) << *this;

       *this = strm.str();

       return (*this);

}





/////////////////////////////////////////////////////////////////

// Conversion functions



void SString::fromLong(long l)

{

       std::stringstream strstream;

       strstream << l;

       *this = strstream.str();

}



const SString &SString::fromFloat(float f, int dp)

{

       std::stringstream strstream;

       if ( dp != -1 ) {

              strstream.precision(dp);

              strstream << std::fixed << f;

       }

       else

              strstream << f;

       *this = strstream.str();

       return (*this);

}



void SString::fromDouble(double f)

{

       std::stringstream strstream;

       strstream << f;

       *this = strstream.str();

}



const SString &SString::fromDouble(double f, int dp)

{

       std::stringstream strstream;

       if (dp != -1) {

              strstream.precision(dp);

              strstream << std::fixed << f;

       }

       else

              strstream << f;

       *this = strstream.str();

       return (*this);

}



const SString &SString::format(const char *sFormat, ...)

{

       char buffer[1024];

       va_list args;

       va_start (args, sFormat);

       vsprintf (buffer, sFormat, args);

       va_end (args);



       this->assign(buffer);

       return (*this);

}



const SString SString::args(const SString *args, int max) const

{

       Utils::SString str = (*this);

       for (int i = 0; i < max; i++)

       {

              Utils::SString find("%");

              find += Utils::SString::Number(i + 1);



              str = str.findReplace(find, args[i]);

       }



       return str;

}

const SString &SString::arg(const SString &s1)

{

       (*this) = this->findReplace("%1", s1);

       return (*this);

}



const SString &SString::arg(const SString &s1, const SString &s2)

{

       (*this) = this->arg(s1).findReplace("%2", s2);

       return (*this);

}

const SString &SString::arg(const SString &s1, const SString &s2, const SString &s3)

{

       (*this) = this->arg(s1, s1).findReplace("%3", s3);

       return (*this);

}

const SString &SString::arg(const SString &s1, const SString &s2, const SString &s3, const SString &s4)

{

       (*this) = this->arg(s1, s2, s3).findReplace("%4", s4);

       return (*this);

}

const SString &SString::arg(const SString &s1, const SString &s2, const SString &s3, const SString &s4, const SString &s5)

{

       (*this) = this->arg(s1, s2, s3, s4).findReplace("%5", s5);

       return (*this);

}





SString SString::Null()

{

       return Utils::SString();

}



SString SString::FromFloat(float f, int dp)

{ 

       SString str;

       str.fromFloat(f, dp); 

       return str;

}



SString SString::Format(const char *sFormat, ...)

{

       char buffer[1024];

       va_list args;

       va_start (args, sFormat);

       vsprintf (buffer, sFormat, args);

       va_end (args);



       return SString(buffer);

}



bool SString::toBool() const

{

       return atoi(this->c_str()) ? true : false;

}

long SString::toLong() const

{

       return static_cast<long>(atoi(this->c_str()));

}

int SString::toInt() const

{

       return static_cast<int>(atoi(this->c_str()));

}

double SString::toDouble() const

{

       return atof(this->c_str());

}

float SString::toFloat() const

{

       return (float)atof(this->c_str());

}



const Utils::WString SString::toWString() const 

{ 

       return s2ws(*this); 

}





const SString &SString::operator= ( const char *str )                          { this->assign(str); return (*this); }

const SString &SString::operator= ( const unsigned char *str )          { this->assign((const char *)str); return (*this); }

const SString &SString::operator= ( const SString &str )                     { this->assign((std::string &)str); return (*this); }

const SString &SString::operator= ( const std::string &str )              { this->assign(str); return (*this); }

const SString &SString::operator= ( unsigned char c )                          { this->assign(1, c); return (*this); }

const SString &SString::operator= ( char c )                                          { this->assign(1, c); return (*this); }

const SString &SString::operator= ( long l )                                          { this->fromLong(l); return (*this); }

const SString &SString::operator= ( unsigned long l )                          { this->fromLong(l); return (*this); }

const SString &SString::operator= ( float f )                                        { this->fromFloat(f); return (*this); }

const SString &SString::operator= ( double f )                                      { this->fromDouble(f); return (*this); }



const unsigned char SString::operator[] ( int num ) const                   { return this->at(num); }

unsigned char &SString::operator[] ( int num )                                      { return (unsigned char &)this->at(num); }



const SString &SString::operator+= ( const char *str )                        { this->append(str); return (*this); }

const SString &SString::operator+= ( const unsigned char *str )        { this->append((const char *)str); return (*this); }

const SString &SString::operator+= ( const std::string &str )            { this->append(str); return (*this); }

const SString &SString::operator+= ( const SString &str )                   { this->append(str); return (*this); }

const SString &SString::operator+= ( const char c )                             { this->append(1, c); return (*this); }

const SString &SString::operator+= ( const unsigned char c )              { this->append(1, c); return (*this); }

const SString &SString::operator+= ( const unsigned long l )              

{ 

       std::stringstream strm;

       strm << (*this) << l;

       strm >> (*this);

       return (*this); 

}

const SString &SString::operator+= ( const long l )        

{ 

       std::stringstream strm;

       strm << (*this) << l;

       *this = strm.str();

       return (*this); 

}

const SString &SString::operator+= ( const float f )              

{ 

       std::stringstream strm;

       strm << (*this) << f;

       *this = strm.str();

       return (*this); 

}

const SString &SString::operator+= ( const double f )            

{ 

       std::stringstream strm;

       strm << (*this) << f;

       *this = strm.str();

       return (*this); 

}





SString SString::operator+ ( const char *str ) const                     { return SString(*this) += str; }

SString SString::operator+ ( const unsigned char *str ) const     { return SString(*this) += str; }

SString SString::operator+ ( const std::string &str ) const        { return SString(*this) += str; }

SString SString::operator+ ( const SString &str ) const               { return SString(*this) += str; }

SString SString::operator+ ( const char c ) const                          { return SString(*this) += c; }

SString SString::operator+ ( const unsigned char c ) const          { return SString(*this) += c; }

SString SString::operator+ ( const long l ) const                          { return SString(*this) += l; }

SString SString::operator+ ( const unsigned long l ) const          { return SString(*this) += l; }

SString SString::operator+ ( const float f ) const                        { return SString(*this) += f; }

SString SString::operator+ ( const double f ) const                      { return SString(*this) += f; }



bool SString::operator== ( const char *str ) const                        { return (this->compare(str)) ? false : true; }

bool SString::operator== ( const unsigned char *str ) const        { return (this->compare((const char *)str)) ? false : true; }

bool SString::operator== ( const std::string &str ) const            { return (this->compare(str)) ? false : true; }

bool SString::operator== ( const SString &str ) const                   { return (this->compare(str)) ? false : true; }



bool SString::operator!= ( const char *str ) const                        { return (this->compare(str)) ? true : false; }

bool SString::operator!= ( const unsigned char *str ) const        { return (this->compare((const char *)str)) ? true : false; }

bool SString::operator!= ( const std::string &str ) const            { return (this->compare(str)) ? true : false; }

bool SString::operator!= ( const SString &str ) const                   { return (this->compare(str)) ? true : false; }



bool SString::operator !() const

{

       return this->empty();

}



bool SString::Compare(const SString &str, bool bCaseSensative) const

{

       if ( bCaseSensative ) {

              return (this->compare(str) == 0) ? true : false;

       }



       if ( str.length() != this->length() ) return false;

       for ( unsigned int i = 0; i < str.length(); i++ ) {

              if ( tolower(this->at(i)) != tolower(str[i]) ) {

                     return false;

              }

       }

       return true;

}



bool SString::Compare(const unsigned char *str, bool bCaseSensative) const

{

       return this->Compare((const char *)str, bCaseSensative);

}



bool SString::Compare(const char *str, bool bCaseSensative) const

{

       if ( bCaseSensative ) {

              return (this->compare(str) == 0) ? true : false;

       }



       if ( strlen(str) != this->length() ) return false;

       for ( unsigned int i = 0; i < this->length(); i++ ) {

              if ( tolower(this->at(i)) != tolower(*(str + i)) ) {

                     return false;

              }

       }



       return true;

}



SString SString::token(const char *token, int tok) const

{

       return this->tokens(token, tok, tok);

}



SString SString::tokens(const char *token, int from, int to) const

{

       if ( this->empty() ) return "";



       int max = this->countToken(token);



       Utils::SString newstr;



       int whichtok = 1;

       Utils::SString::size_type lastPos = 0;

       Utils::SString::size_type pos     = _token_nextPos(token, 0);



       if ( from < 0 )

              from = max + (from + 1);

       if ( to < 0 )

              to = max + (to + 1);



       while (Utils::SString::npos != pos || Utils::SString::npos != lastPos)

       {

              if ( to == 0 )

              {

                     if ( whichtok >= from )

                     {

                            if ( newstr != "" ) newstr = newstr + token;

                            newstr = newstr + Utils::SString(this->substr(lastPos, pos - lastPos));

                     }

              }

              else

              {

                     if ( (whichtok >= from) && (whichtok <= to) )

                     {

                            if ( newstr != "" ) newstr = newstr + token;

                            newstr = newstr + Utils::SString(this->substr(lastPos, pos - lastPos));

                     }

                     if ( whichtok > to )

                            break;

              }

              // Found a token, add it to the vector.

              whichtok++;



              if ( pos >= this->length() )

                     break;



              // skip past token

              size_t i = 0;

              size_t max = strlen(token);

              lastPos = pos;

              while ( (i < max) && (token[i] == this->at(lastPos)) )

              {

                     ++i;

                     ++lastPos;

              }



              // get the next token

              pos = _token_nextPos(token, lastPos);

       }

       return newstr;

}



SString SString::remToken(const char* token, int from) const

{

       Utils::SString newstr;



       if (from < 0)

       {

              int maxT = this->countToken(token);

              from = maxT + (from + 1);

       }



       int whichtok = 1;

       Utils::SString::size_type lastPos = 0;

       Utils::SString::size_type pos = _token_nextPos(token, 0);



       while (Utils::SString::npos != pos || Utils::SString::npos != lastPos)

       {

              if (whichtok != from)

              {

                     if (newstr != "") newstr = newstr + token;

                     newstr = newstr + Utils::SString(this->substr(lastPos, pos - lastPos));

              }



              // Found a token, add it to the vector.

              whichtok++;



              if (pos >= this->length())

                     break;



              // skip past token

              size_t i = 0;

              size_t max = strlen(token);

              lastPos = pos;

              while ((i < max) && (token[i] == this->at(lastPos)))

              {

                     ++i;

                     ++lastPos;

              }



              // get the next token

              pos = _token_nextPos(token, lastPos);

       }

       return newstr;

}



SString SString::remTokens(const char* token, int from, int to) const

{

       Utils::SString newstr;



       if (from < 0)

       {

              int maxT = this->countToken(token);

              from = maxT + (from + 1);

       }

       if (to < 0)

       {

              int maxT = this->countToken(token);

              to = maxT + (to + 1);

       }



       int whichtok = 1;

       Utils::SString::size_type lastPos = 0;

       Utils::SString::size_type pos = _token_nextPos(token, 0);



       while (Utils::SString::npos != pos || Utils::SString::npos != lastPos)

       {

              if (!(whichtok >= from && whichtok <= to))

              {

                     if (newstr != "") newstr = newstr + token;

                     newstr = newstr + Utils::SString(this->substr(lastPos, pos - lastPos));

              }



              // Found a token, add it to the vector.

              whichtok++;



              if (pos >= this->length())

                     break;



              // skip past token

              size_t i = 0;

              size_t max = strlen(token);

              lastPos = pos;

              while ((i < max) && (token[i] == this->at(lastPos)))

              {

                     ++i;

                     ++lastPos;

              }



              // get the next token

              pos = _token_nextPos(token, lastPos);

       }

       return newstr;

}



SString SString::word(int word) const

{

       return this->token(" ", word);

}

SString SString::words(int from, int to) const

{

       return this->tokens(" ", from, to);

}



SString SString::addToken(const char *token, const Utils::SString &str) const

{

       if (this->empty())

              return str;



       Utils::SString s = (*this);

       s += token;

       s += str;



       return s;

}



int SString::countToken(const char *token) const

{

       if ( this->empty() )

              return 0;



       // finds the number of tokens in a string

       int found = 1;



       Utils::SString tmpstr = *this;



       // ignore the initial spaces

       Utils::SString::size_type pos = this->find_first_not_of(token, 0);



       // remove end spaces

       size_t i = tmpstr.size() - 1;

       while ( tmpstr[i] == ' ' && i > 0 )

              i--;

       if ( i <= 0 ) return 0;

       tmpstr.erase ( i + 1, tmpstr.size() - i );



       // count tokens

       pos = tmpstr.find (token,pos + 1);

       while ( pos < Utils::SString::npos )

       {

              while (tmpstr[pos] == ' ')

                     pos++;

              found++;

              pos = tmpstr.find (token,pos + 1);

       }



       // return number of tokens

       return found;

}



Utils::SString::size_type SString::_token_nextPos(const char *token, Utils::SString::size_type curPos) const

{

       bool found = false;

       Utils::SString::size_type startPos = 0;

       size_t max = strlen(token);

       while ( !found ) {

              found = true;

              startPos = this->find_first_of(token[0], curPos);

              if ( startPos == Utils::SString::npos ) {

                     startPos = this->length();

                     break;

              }



              Utils::SString::size_type pos = startPos;

              size_t i = 1;

              while ( i < max )

              {

                     ++pos;

                     if ( this->at(pos) != token[i] )

                     {

                            found = false;

                            break;

                     }

                     ++i;

              }

              curPos = pos;

       }

       return startPos;

}



SString SString::findReplace(const SString &find, const SString &replace ) const

{

       Utils::SString newstr = *this;

       Utils::SString::size_type pos = newstr.find(find, 0);

       while ( pos < Utils::SString::npos ) {

              newstr.replace(pos, find.length(), replace);

              pos = newstr.find(find, pos + replace.length());

       }



       return newstr;

}



SString SString::findRemove(const SString &find) const

{

       Utils::SString replace = *this;



       Utils::SString::size_type pos = replace.find(find, 0 );

       while ( pos != Utils::SString::npos ) {

              replace.erase ( pos, find.length() );

              pos = replace.find(find, pos);

       }



       return replace;

}



SString SString::removeIf(int iChar, char c) const

{

       Utils::SString newStr = *this;

       if ( newStr.empty() ) return newStr;

       if ( this->at(iChar) == c ) newStr.erase(iChar, 1);

       return newStr;

}



SString SString::stripHtml() const

{

       // if empty, theres no to strip

       if ( this->empty() ) return "";



       // replace break line with a new line

       Utils::SString newStr = (*this);

       newStr = newStr.findReplace("<br/>", "\n");

       newStr = newStr.findReplace("<br />", "\n");

       newStr = newStr.findReplace("<p>", "\n\t");

       newStr = newStr.findReplace("</p>", "\n");



       // find any remaining tags and remove them

       Utils::SString::size_type pos     = newStr.find_first_of('<', 0);

       Utils::SString::size_type lastPos = newStr.find_first_of('>', pos);



       while (Utils::SString::npos != pos || Utils::SString::npos != lastPos)

       {

              if ( lastPos > newStr.length() ) break;

              // remove the tag

              newStr.erase(pos, lastPos + 1);



              // find the next tag

              pos = newStr.find_first_of('<', pos);

              lastPos = newStr.find_first_of('>', pos);

       }



       // now remove all the starting new lines

       while ( newStr[0] == '\n' || newStr[0] == '\t' ) newStr.erase(0, 1);

       return newStr;

}



bool SString::contains(const SString &str, bool bCaseSensative) const

{

       if (bCaseSensative) return (this->find(str, 0) == Utils::SString::npos) ? false : true;



       SString thisLower = this->lower();

       SString strLower = str.lower();

       return (thisLower.find(strLower, 0) == Utils::SString::npos) ? false : true;

}

bool SString::containsAny(const SString &str, bool bCaseSensative) const

{

       char *c = (char *)str.c_str();

       while (*c != 0)

       {

              char c1 = *c;

              if (contains(c1))

                     return true;

              c++;

       }



       return false;

}

bool SString::isin(const SString &str, bool bCaseSensative) const

{

       return contains(str, bCaseSensative);

}



int SString::findPos(const SString &find, int iStartPos) const

{

       Utils::SString::size_type pos = this->find(find, iStartPos);

       if ( pos == Utils::SString::npos ) return -1;

       return pos;

}



bool SString::isin(char c, bool bCaseSensative) const

{

       return contains(c, bCaseSensative);

}

bool SString::contains(char c, bool bCaseSensative) const

{

       bool f = false;

       for ( unsigned int i = 0; i < this->length(); i++ )

       {

              bool bCheck = (bCaseSensative) ? (this->at(i) == c) : (tolower(this->at(i)) == tolower(c));

              if ( bCheck ) {

                     f = true;

                     break;

              }

       }

       return f;

}



SString SString::between(const SString &before, const SString &after) const

{

       int pos = this->findPos(before);

       if ( pos >= 0 ) {

              pos += before.length();

              int end = this->findPos(after, pos);

              if ( end >= 0 ) return this->substr(pos, end - pos);

       }



       return "";

}



SString SString::mid(int start, int end) const

{

       if (end <= 0)

              end = this->length() + end;

       return this->substr(start, end - start);

}

SString SString::left(long num) const

{

       if ( num < 0 )

              num = (long)this->length() + num;

       if ( num > (long)this->length() )

              num = (long)this->length();



       return this->substr(0, num);

}



SString SString::right(int num) const

{

       if ( num > 0 ) num -= (int)this->length();

       if ( num < -(int)this->length() ) num = -(int)this->length();



       return this->substr(-num);

}



const SString &SString::readToEndOfLine(FILE *id, int *line, bool upper)

{

       (*this) = "";

       char c = fgetc ( id );

       if ( c == -1 )

              return (*this);



       while ( (c != 13) && (!feof(id)) && (c != '\n') )

       {

              (*this) += c;

              c = fgetc ( id );

       }



       if ( line )

              ++(*line);



//   if ( upper )

       //   ToUpper ();



       return (*this);

}



char *SString::readToEndOfLine(char *data)

{

       return (char *)this->readToEndOfLine((unsigned char *)data);

}

unsigned char *SString::readToEndOfLine(unsigned char *data)

{

       int pos = 0;



       // do until we get a line break

       while ( (data[pos] != 13) && (data[pos] != 0) && (data[pos] != '\n') ) {

              ++pos;

       }



       if ( !pos ) {

              this->clear();

       }

       else {

              if ( pos > 2000 ) {

                     char *d = new char[pos + 1];

                     memcpy(d, data, pos);

                     d[pos] = 0;

                     *this = d;

                     delete d;

              }

              else {

                     char d[2000];

                     memcpy(d, data, pos);

                     d[pos] = 0;

                     *this = d;

              }

       }



       if ( data[pos] == 0 ) return NULL;

       return data + (pos + 1);

}



SString SString::replaceToken(const char *token, int from, const SString &replace) const

{

       Utils::SString newstr;



       int whichtok = 1;

       Utils::SString::size_type lastPos = 0;

       Utils::SString::size_type pos     = _token_nextPos(token, 0);



       while (Utils::SString::npos != pos || Utils::SString::npos != lastPos)

       {

              if ( whichtok == from )

              {

                     if ( newstr != "" ) newstr = newstr + token;

                     newstr = newstr + replace;

              }

              else

              {

                     if ( newstr != "" ) newstr = newstr + token;

                     newstr = newstr + Utils::SString(this->substr(lastPos, pos - lastPos));

              }



              // Found a token, add it to the vector.

              whichtok++;



              if ( pos >= this->length() )

                     break;



              // skip past token

              size_t i = 0;

              size_t max = strlen(token);

              lastPos = pos;

              while ( (i < max) && (token[i] == this->at(lastPos)) )

              {

                     ++i;

                     ++lastPos;

              }



              // get the next token

              pos = _token_nextPos(token, lastPos);

       }

       return newstr;

}





SString *SString::tokenise(const char *token, int *max) const

{

       if ( empty() ) {

              *max = 0;

              return NULL;

       }



       *max = this->countToken(token);



       if ( (*max) <= 0 ) {

              *max = 0;

              return NULL;

       }



       SString *newstr = (*max == 1) ? new SString : new SString[*max];



       int whichtok = 0;

       // get first token

       Utils::SString::size_type lastPos = 0;

       Utils::SString::size_type pos     = this->_token_nextPos(token, 0);



       while (Utils::SString::npos != pos || Utils::SString::npos != lastPos)

       {

              // set token

              if ( *max == 1 ) *newstr = this->substr(lastPos, pos - lastPos);

              else                       newstr[whichtok] = this->substr(lastPos, pos - lastPos);



              // move to next token

              whichtok++;

              if ( whichtok >= *max )

                     break;



              if ( pos >= this->length() )

                     break;



              // skip past token

              size_t i = 0;

              size_t max = strlen(token);

              lastPos = pos;

              while ( (i < max) && (token[i] == this->at(lastPos)) ) {

                     ++i;

                     ++lastPos;

              }



              // get the next token

              pos = _token_nextPos(token, lastPos);

       }



       return newstr;

}



const SString &SString::removeChar(const char *cs)

{

       char *current = const_cast<char *>(cs);

       while ( current[0] != '\0' ) {

              removeChar(current[0]);

              ++current;

       }



       return (*this);

}



const SString &SString::removeChar(char c)

{

       Utils::SString::size_type pos = this->find_first_of(c, 0);

       while(pos != Utils::SString::npos) {

              this->erase(pos, 1);

              pos = this->find_first_of(c, 0);

       }



       return (*this);

}



SString SString::remove(char c) const

{

       SString newStr = *this;



       Utils::SString::size_type pos = newStr.find_first_of(c, 0);

       while(pos != Utils::SString::npos) {

              newStr.erase(pos, 1);

              pos = newStr.find_first_of(c, 0);

       }



       return newStr;

}



bool SString::_isCharNumber(char c) const

{

       return (c >= '0' && c <= '9') ? true : false;

}



bool SString::isCharNumber(int c) const

{

       return _isCharNumber(this->at(c));

}



bool SString::isNumber(bool integer) const

{

       bool foundpoint = integer;

       for ( int i = 0; i < (int)this->length(); i++ )

       {

              // check for a decimal point (floating point value)

              // only allow 1 decimal point, or none if just checking for an integer

              if ( this->at(i) == '.' && !foundpoint ) foundpoint = true;

              // check if it is a number, 0-9

              else if ( !this->isCharNumber(i) ) return false;

       }

       return true;

}



const SString &SString::removeFirstSpace()

{

       Utils::SString::size_type pos = this->find_first_not_of(" \t\f\v\n\r", 0);

       if ( pos != Utils::SString::npos ) {

              this->erase(0, pos);

       }

       else

              this->clear();

       return (*this);

}

const SString &SString::removeEndSpace()

{

       Utils::SString::size_type pos = this->find_last_not_of(" \t\f\v\n\r");

       if ( pos != Utils::SString::npos ) {

              this->erase(pos + 1);

       }

       else

              this->clear();

       return (*this);

}



const SString &SString::truncate(int iNum)

{

       size_t pos = iNum;

       if ( iNum < 0 ) pos = this->length() + iNum;

       this->erase(pos, this->length() - pos);

       return (*this);

}



SString SString::lower() const

{

       Utils::SString newStr(*this);

       std::transform(this->begin(), this->end(), newStr.begin(), tolower);

       return newStr;

}



SString SString::upper() const

{

       Utils::SString newStr(*this);

       std::transform(this->begin(), this->end(), newStr.begin(), toupper);

       return newStr;

}

const SString &SString::toLower()

{

       std::transform(this->begin(), this->end(), this->begin(), tolower);

       return (*this);

}



const SString &SString::toUpper()

{

       std::transform(this->begin(), this->end(), this->begin(), toupper);

       return (*this);

}



const SString &SString::toFilename()

{

       (*this) = (*this).findReplace("\\", "/").findReplace("//", "/");

       return (*this);

}

SString SString::asFilename() const

{

       Utils::SString sFile(*this);

       return sFile.toFilename();

}



int SString::compareVersion(const Utils::SString &sV) const

{

       Utils::SString thisStr = (*this);

       Utils::SString checkStr = sV;



       int section = 1;



       // remove any rc/beta version

       int beta1 = 0;

       int beta2 = 0;



       int len = 2;

       int pos = thisStr.findPos("rc", 0);

       if ( pos == -1 ) { pos = thisStr.findPos("beta", 0); len = 4; }

//          if ( pos == -1 ) { pos = thisStr.findPos("²", 0); len = 1; }

       if ( pos != -1 ) {

              beta1 = -(long)thisStr.right(-(pos + len)).remove(' ');

              thisStr = thisStr.left(pos).removeEndSpace();

       }



       len = 2;

       pos = checkStr.findPos("rc", 0);

       if ( pos == -1 ) { pos = checkStr.findPos("beta", 0); len = 4;}

//          if ( pos == -1 ) { pos = v.findPos("²", 0); len = 1; }

       if ( pos != -1 ) {

              beta2 = checkStr.right(-(pos + len)).remove(' ');

              checkStr = checkStr.left(pos).removeEndSpace();

       }



       bool isDecimal = thisStr.countToken(".") == 2 && checkStr.countToken(".") == 2;



       while ( true ) {

              Utils::SString sNum1 = thisStr.token(".", section);

              Utils::SString sNum2 = checkStr.token(".", section);



              // no number nubmers, must be the same

              if ( sNum1.empty() && sNum2.empty() ) {

                     // compare the beta/rc version

                     if ( beta1 == beta2 )

                            return COMPARE_SAME;

                     if ( beta1 && !beta2 ) // new isn't a beta, so it must be higher

                            return COMPARE_NEWER;

                     if ( beta2 && !beta1 ) // old isn't a beta, so it must be higher

                            return COMPARE_OLDER;

                     if ( beta1 < 0 && beta2 > 0 ) // old is an rc and new is only a beta

                            return COMPARE_OLDER;

                     if ( beta2 < 0 && beta1 > 0 ) // new is an rc and old is only a beta

                            return COMPARE_NEWER;

                     // otherwise they are the same

                     if ( beta1 > 0 ) {

                            if ( beta1 > beta2 )

                                   return COMPARE_OLDER;

                            else

                                   return COMPARE_NEWER;

                     }

                     if ( beta1 < 0 ) {

                            if ( beta1 < beta2 )

                                   return COMPARE_OLDER;

                            else

                                   return COMPARE_NEWER;

                     }

                     // failsale, we should never get here

                     return COMPARE_SAME;

              }



              // one has more sections, most likly its the newer ones, ie, 1.00 v 1.00.1, 1.00.1 will be newer

              if ( sNum1.empty() )

                     return COMPARE_NEWER;

              else if ( sNum2.empty() )

                     return COMPARE_OLDER;



              // check if we have any letters at the end

              char cNum1 = 0, cNum2 = 0;

              if ( !sNum1.isCharNumber((int)sNum1.length() - 1) )

              {

                     cNum1 = toupper(sNum1[(int)sNum1.length() - 1]);

                     sNum1.truncate(-1);

              }

              if ( !sNum2.isCharNumber((int)sNum2.length() - 1) )

              {

                     cNum2 = toupper(sNum2[(int)sNum2.length() - 1]);

                     sNum2.truncate(-1);

              }



              // now make sure each section is the correct length

              if ( isDecimal && section > 1 )

              {

                     while ( sNum1.length() < sNum2.length() )

                            sNum1 += "0";

                     while ( sNum2.length() < sNum1.length() )

                            sNum2 += "0";

              }



              // check the values of the current section

              int iNum1 = sNum1;

              int iNum2 = sNum2;



              if ( iNum1 > iNum2 )

                     return COMPARE_OLDER;

              if ( iNum2 > iNum1 )

                     return COMPARE_NEWER;



              // now compare the "letter" version, only test if one has a letter

              if ( cNum1 || cNum2 )

              {

                     if ( !cNum1 )

                            return COMPARE_NEWER;

                     if ( !cNum2 )

                            return COMPARE_OLDER;



                     if ( cNum2 > cNum1 )

                            return COMPARE_NEWER;

                     else if ( cNum1 > cNum2 )

                            return COMPARE_OLDER;

              }



              // move to the next section

              ++section;

       }



       return COMPARE_SAME;

}



bool SString::match(const Utils::SString &pattern) const

{

       enum State {

              Exact,      // exact match

              Any,              // ?

              AnyRepeat   // *

       };



       const char *s = this->c_str();

       const char *p = pattern.c_str();

       const char *q = 0;

       int state = 0;



       bool match = true;

       while (match && *p) {

              if (*p == '*') {

                     state = AnyRepeat;

                     q = p + 1;

              }

              else if (*p == '?') state = Any;

              else state = Exact;



              if (*s == 0) break;



              switch (state) {

              case Exact:

                     match = *s == *p;

                     s++;

                     p++;

                     break;



              case Any:

                     match = true;

                     s++;

                     p++;

                     break;



              case AnyRepeat:

                     match = true;

                     s++;



                     if (*s == *q) p++;

                     break;

              }

       }



       if (state == AnyRepeat) return (*s == *q);

       else if (state == Any) return (*s == *p);

       else return match && (*s == *p);

}



void SString::_assign(const wchar_t* str)

{ 

       this->assign(ws2s(str)); 

}

void SString::_assign(const wchar_t* str, size_t len) 

{ 

       this->assign(ws2s(str), len); 

}



}//NAMESPACE