Subversion Repositories spk

Rev

Rev 130 | Rev 160 | 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>



namespace Utils {



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

{

       return String(str1) + str2;

}



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

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

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

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

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

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

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

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

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

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

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



String::~String(void)

{

}



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

{

       String str(iNumber);

       return str.padNumber(iAmount);

}



const String &String::padNumber(int iAmount)

{

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

}



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

{

       std::stringstream strm;

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

       *this = strm.str();

       return (*this);

}





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

// Conversion functions



void String::fromLong(long l)

{

       std::stringstream strstream;

       strstream << l;

       *this = strstream.str();

}



const String &String::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 String::fromDouble(double f)

{

       std::stringstream strstream;

       strstream << f;

       *this = strstream.str();

}



const String &String::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 String &String::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 String String::args(const String *args, int max) const

{

       Utils::String str = (*this);

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

       {

              Utils::String find("%");

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



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

       }



       return str;

}

const String &String::arg(const String &s1)

{

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

       return (*this);

}



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

{

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

       return (*this);

}

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

{

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

       return (*this);

}

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

{

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

       return (*this);

}

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

{

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

       return (*this);

}





String String::Null()

{

       return Utils::String();

}



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

{ 

       String str;

       str.fromFloat(f, dp); 

       return str;

}



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

{

       char buffer[1024];

       va_list args;

       va_start (args, sFormat);

       vsprintf (buffer, sFormat, args);

       va_end (args);



       return String(buffer);

}



bool String::toBool() const

{

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

}

long String::toLong() const

{

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

}

int String::toInt() const

{

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

}

double String::toDouble() const

{

       return atof(this->c_str());

}

float String::toFloat() const

{

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

}





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

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

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

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

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

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

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

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

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

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



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

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



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

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

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

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

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

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

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

{ 

       std::stringstream strm;

       strm << (*this) << l;

       strm >> (*this);

       return (*this); 

}

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

{ 

       std::stringstream strm;

       strm << (*this) << l;

       *this = strm.str();

       return (*this); 

}

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

{ 

       std::stringstream strm;

       strm << (*this) << f;

       *this = strm.str();

       return (*this); 

}

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

{ 

       std::stringstream strm;

       strm << (*this) << f;

       *this = strm.str();

       return (*this); 

}





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

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

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

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

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

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

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

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

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

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



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

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

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

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



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

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

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

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



bool String::operator !() const

{

       return this->empty();

}



bool String::Compare(const String &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 String::Compare(const unsigned char *str, bool bCaseSensative) const

{

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

}



bool String::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;

}



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

{

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

}



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

{

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



       int max = this->countToken(token);



       Utils::String newstr;



       int whichtok = 1;

       Utils::String::size_type lastPos = 0;

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



       if ( from < 0 )

              from = max + (from + 1);

       if ( to < 0 )

              to = max + (to + 1);



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

       {

              if ( to == 0 )

              {

                     if ( whichtok >= from )

                     {

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

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

                     }

              }

              else

              {

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

                     {

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

                            newstr = newstr + Utils::String(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;

}



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

{

       Utils::String newstr;



       if (from < 0)

       {

              int maxT = this->countToken(token);

              from = maxT + (from + 1);

       }



       int whichtok = 1;

       Utils::String::size_type lastPos = 0;

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



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

       {

              if ( whichtok != from )

              {

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

                     newstr = newstr + Utils::String(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;

}



String String::word(int word) const

{

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

}

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

{

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

}



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

{

       if (this->empty())

              return str;



       Utils::String s = (*this);

       s += token;

       s += str;



       return s;

}



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

{

       if ( this->empty() )

              return 0;



       // finds the number of tokens in a string

       int found = 1;



       Utils::String tmpstr = *this;



       // ignore the initial spaces

       Utils::String::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::String::npos )

       {

              while (tmpstr[pos] == ' ')

                     pos++;

              found++;

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

       }



       // return number of tokens

       return found;

}



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

{

       bool found = false;

       Utils::String::size_type startPos = 0;

       size_t max = strlen(token);

       while ( !found ) {

              found = true;

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

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

                     startPos = this->length();

                     break;

              }



              Utils::String::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;

}



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

{

       Utils::String newstr = *this;

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

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

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

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

       }



       return newstr;

}



String String::findRemove(const String &find) const

{

       Utils::String replace = *this;



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

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

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

              pos = replace.find(find, pos);

       }



       return replace;

}



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

{

       Utils::String newStr = *this;

       if ( newStr.empty() ) return newStr;

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

       return newStr;

}



String String::stripHtml() const

{

       // if empty, theres no to strip

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



       // replace break line with a new line

       Utils::String 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::String::size_type pos     = newStr.find_first_of('<', 0);

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



       while (Utils::String::npos != pos || Utils::String::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 String::contains(const String &str, bool bCaseSensative) const

{

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



       String thisLower = this->lower();

       String strLower = str.lower();

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

}

bool String::containsAny(const String &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 String::isin(const String &str, bool bCaseSensative) const

{

       return contains(str, bCaseSensative);

}



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

{

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

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

       return pos;

}



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

{

       return contains(c, bCaseSensative);

}

bool String::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;

}



String String::between(const String &before, const String &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 "";

}



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

{

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

}

String String::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);

}



String String::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 String &String::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 *String::readToEndOfLine(char *data)

{

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

}

unsigned char *String::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);

}



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

{

       Utils::String newstr;



       int whichtok = 1;

       Utils::String::size_type lastPos = 0;

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



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

       {

              if ( whichtok == from )

              {

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

                     newstr = newstr + replace;

              }

              else

              {

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

                     newstr = newstr + Utils::String(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;

}





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

{

       if ( empty() ) {

              *max = 0;

              return NULL;

       }



       *max = this->countToken(token);



       if ( (*max) <= 0 ) {

              *max = 0;

              return NULL;

       }



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



       int whichtok = 0;

       // get first token

       Utils::String::size_type lastPos = 0;

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



       while (Utils::String::npos != pos || Utils::String::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 String &String::removeChar(const char *cs)

{

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

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

              removeChar(current[0]);

              ++current;

       }



       return (*this);

}



const String &String::removeChar(char c)

{

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

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

              this->erase(pos, 1);

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

       }



       return (*this);

}



String String::remove(char c) const

{

       String newStr = *this;



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

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

              newStr.erase(pos, 1);

              pos = newStr.find_first_of(c, 0);

       }



       return newStr;

}



bool String::_isCharNumber(char c) const

{

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

}



bool String::isCharNumber(int c) const

{

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

}



bool String::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 String &String::removeFirstSpace()

{

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

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

              this->erase(0, pos);

       }

       else

              this->clear();

       return (*this);

}

const String &String::removeEndSpace()

{

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

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

              this->erase(pos + 1);

       }

       else

              this->clear();

       return (*this);

}



const String &String::truncate(int iNum)

{

       size_t pos = iNum;

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

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

       return (*this);

}



String String::lower() const

{

       Utils::String newStr(*this);

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

       return newStr;

}



String String::upper() const

{

       Utils::String newStr(*this);

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

       return newStr;

}

const String &String::toLower()

{

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

       return (*this);

}



const String &String::toUpper()

{

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

       return (*this);

}



const String &String::toFilename()

{

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

       return (*this);

}

String String::asFilename() const

{

       Utils::String sFile(*this);

       return sFile.toFilename();

}



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

{

       Utils::String thisStr = (*this);

       Utils::String 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();

       }



       while ( true ) {

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

              Utils::String 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 ( 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 String::match(const Utils::String &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);

}



}//NAMESPACE