khanat-opennel-code/code/ryzom/tools/phrase_generator/sstring.h
2010-09-24 10:27:31 +02:00

538 lines
12 KiB
C++

// Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
// Copyright (C) 2010 Winch Gate Property Limited
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#ifndef PDSLIB_STRING_H
#define PDSLIB_STRING_H
#include <string>
class CSString: public std::string
{
public:
CSString()
{
}
CSString(const char *s)
{
*(std::string *)this=s;
}
CSString(const std::string &s)
{
*(std::string *)this=s;
}
CSString(char c)
{
*(std::string *)this=c;
}
CSString(int i,const char *fmt="%d")
{
char buf[1024];
sprintf(buf,fmt,i);
*this=buf;
}
CSString(unsigned u,const char *fmt="%u")
{
char buf[1024];
sprintf(buf,fmt,u);
*this=buf;
}
CSString(double d,const char *fmt="%f")
{
char buf[1024];
sprintf(buf,fmt,d);
*this=buf;
}
CSString(const char *s,const char *fmt)
{
char buf[1024];
sprintf(buf,fmt,s);
*this=buf;
}
CSString(const std::string &s,const char *fmt)
{
char buf[1024];
sprintf(buf,fmt,s.c_str());
*this=buf;
}
char operator*()
{
if (empty())
return 0;
return (*this)[0];
}
// return the n right hand most characters of a string
CSString right(unsigned count) const
{
if (count>=size())
return *this;
return substr(size()-count);
}
// return the string minus the n right hand most characters of a string
CSString rightCrop(unsigned count) const
{
if (count>=size())
return CSString();
return substr(0,size()-count);
}
// return the n left hand most characters of a string
CSString left(unsigned count) const
{
return substr(0,count);
}
// return the string minus the n left hand most characters of a string
CSString leftCrop(unsigned count) const
{
if (count>=size())
return CSString();
return substr(count);
}
// return sub string up to but not including first instance of given character
CSString splitTo(char c,bool truncateThis=false)
{
unsigned i;
CSString result;
for (i=0;i<size() && (*this)[i]!=c;++i)
result+=(*this)[i];
// remove the result string from the input string if so desired
if (truncateThis)
{
if (i<size()-1)
(*this)=substr(i+1); // +1 to skip the separator character
else
clear();
}
return result;
}
// return sub string up to but not including first instance of given character
CSString splitTo(const char *s,bool truncateThis=false)
{
unsigned i;
CSString result;
for (i=0;i<size();++i)
{
// perform a quick string compare
int j;
for (j=0;s[j]!=0 && s[j]==(&((*this)[i]))[j];++j)
{
}
// if string compare matched then return result so far
if (s[j]==0)
{
// remove the result string from the input string if so desired
if (truncateThis)
{
if (i<size()-1)
(*this)=substr(i+1); // +1 to skip the separator character
else
clear();
}
return result;
}
result+=(*this)[i];
}
// we didn't find the separator string so we're returning a copy of the whole string
if (truncateThis)
clear();
return result;
}
// return sub string from character following first instance of given character on
CSString splitFrom(char c) const
{
CSString result;
std::string::const_iterator it;
for (it=begin();it!=end() && *it!=c;++it)
{}
if (it!=end())
{
++it;
for (;it!=end();++it)
result+=*it;
}
return result;
}
// return sub string from character following first instance of given character on
CSString splitFrom(const char *s) const
{
unsigned int i;
CSString result;
for (i=0;i<size();++i)
{
// perform a quick string compare
unsigned int j;
for (j=0;i+j<size() && s[j]!=0 && s[j]==(*this)[i+j];++j)
{
}
// if string compare matched then build and return a result
if (s[j]==0)
{
result=substr(i+j);
return result;
}
}
return result;
}
// behave like a s strtok() routine, returning the sun string extracted from (and removed from) *this
CSString strtok(const char *separators)
{
unsigned int i;
CSString result;
// skip leading junk
for (i=0;i<size();++i)
{
// look for the next character in the 'separator' character list supplied
unsigned j;
for (j=0;separators[j] && (*this)[i]!=separators[j];++j)
{}
// if not found then we're at end of leading junk
if (!separators[j])
break;
}
// copy out everything up to the next separator character
for (;i<size();++i)
{
// look for the next character in the 'separator' character list supplied
unsigned j;
for (j=0;separators[j] && (*this)[i]!=separators[j];++j)
{}
// if not found then we're at end of leading junk
if (separators[j])
break;
result+=(*this)[i];
}
// skip trailing junk
for (;i<size();++i)
{
// look for the next character in the 'separator' character list supplied
unsigned j;
for (j=0;separators[j] && (*this)[i]!=separators[j];++j)
{}
// if not found then we're at end of leading junk
if (!separators[j])
break;
}
// delete the treated bit from this string
(*this)=substr(i);
return result;
}
// return first word (blank separated)
CSString firstWord(bool truncateThis=false)
{
CSString result;
unsigned i=0;
// skip white space
for (i=0;i<size() && isWhiteSpace((*this)[i]);++i)
{}
if ( ((*this)[i]>='A' && (*this)[i]<='Z') || ((*this)[i]>='a' && (*this)[i]<='z') ||
((*this)[i]>='0' && (*this)[i]<='9') || (*this)[i]=='_')
{
// copy out an alpha-numeric string
for (;i<(*this).size() &&
( ((*this)[i]>='A' && (*this)[i]<='Z') || ((*this)[i]>='a' && (*this)[i]<='z') ||
((*this)[i]>='0' && (*this)[i]<='9') || (*this)[i]=='_')
;++i)
result+=(*this)[i];
}
else
{
// just take the first character of the input
result=(*this)[i];
++i;
}
// remove the result string from the input string if so desired
if (truncateThis)
{
if (i<size())
(*this)=substr(i);
else
clear();
}
return result;
}
CSString firstWordConst() const
{
return const_cast<CSString *>(this)->firstWord();
}
// return sub string up to but not including first instance of given character
CSString tailFromFirstWord() const
{
CSString hold=*this;
hold.firstWord(true);
return hold;
}
// count the number of words (or quote delimited sub-strings) in a string
unsigned countWords() const
{
unsigned count=0;
CSString hold=strip();
while (!hold.empty())
{
hold=hold.tailFromFirstWord().strip();
++count;
}
return count;
}
// count the number of words (or quote delimited sub-strings) in a string
CSString word(unsigned idx) const
{
CSString hold=strip();
for (unsigned count=0;count<idx;++count)
hold=hold.tailFromFirstWord().strip();
return hold.firstWord();
}
// return first word or quote-encompassed sub-string
CSString firstWordOrWords(bool truncateThis=false)
{
CSString hold=strip();
if (hold[0]!='\"')
return firstWord(truncateThis);
// the string is quote enclosed
CSString result;
unsigned i=1; // skip leading quote
// copy from character following opening quote to char preceding closing quote (or end of string)
while (i<hold.size() && hold[i]!='\"')
{
result+=hold[i];
++i;
}
// remove the result string from the input string if so desired
if (truncateThis)
{
if (i<size()-1)
(*this)=substr(i+1); // +1 to skip the closing quote
else
clear();
}
return result;
}
CSString firstWordOrWordsConst() const
{
return const_cast<CSString *>(this)->firstWordOrWords();
}
// return sub string up to but not including first instance of given character
CSString tailFromFirstWordOrWords() const
{
CSString hold=*this;
hold.firstWordOrWords(true);
return hold;
}
// count the number of words (or quote delimited sub-strings) in a string
unsigned countWordOrWords() const
{
unsigned count=0;
CSString hold=strip();
while (!hold.empty())
{
hold=hold.tailFromFirstWordOrWords().strip();
++count;
}
return count;
}
// count the number of words (or quote delimited sub-strings) in a string
CSString wordOrWords(unsigned idx) const
{
CSString hold=strip();
for (unsigned count=0;count<idx;++count)
hold=hold.tailFromFirstWordOrWords().strip();
return hold.firstWordOrWords();
}
// a handy utility routine for knowing if a character is a white space character or not
static bool isWhiteSpace(char c) { return c==' ' || c=='\t' || c=='\n' || c=='\r' || c==26; }
// return a copy of the string with leading and trainling spaces rmoved
CSString strip() const
{
CSString result;
int i,j;
for (j=size()-1; j>=0 && isWhiteSpace((*this)[j]); --j) {}
for (i=0; i<j && isWhiteSpace((*this)[i]); ++i) {}
for (; i<=j; ++i)
result+=(*this)[i];
return result;
}
// making an upper case copy of a string
CSString toUpper() const
{
CSString result;
std::string::const_iterator it;
for (it=begin();it!=end();++it)
{
char c=(*it);
if (c>='a' && c<='z')
c^=('a'^'A');
result+=c;
}
return result;
}
// making a lower case copy of a string
CSString toLower() const
{
CSString result;
std::string::const_iterator it;
for (it=begin();it!=end();++it)
{
char c=(*it);
if (c>='A' && c<='Z')
c^=('a'^'A');
result+=c;
}
return result;
}
// replacing all occurences of one string with another
CSString replace(const char *toFind,const char *replacement) const
{
// just bypass the problems that can cause a crash...
if (toFind==NULL || *toFind==0)
return *this;
unsigned i,j;
CSString result;
for (i=0;i<size();)
{
// string compare toFind against (*this)+i ...
for (j=0;toFind[j];++j)
if ((*this)[i+j]!=toFind[j])
break;
// if strings were identical then j reffers to ASCIIZ terminator at end of 'toFind'
if (toFind[j]==0)
{
if (replacement!=NULL)
result+=replacement;
i+=j;
}
else
{
result+=(*this)[i];
++i;
}
}
return result;
}
// find index at which a sub-string starts - if sub-string not found then returns size()
unsigned find(const char *toFind,unsigned startLocation=0) const
{
// just bypass the problems that can cause a crash...
if (toFind==NULL || *toFind==0 || startLocation>size())
return size();
unsigned i,j;
for (i=startLocation;i<size();++i)
{
// string compare toFind against (*this)+i ...
for (j=0;toFind[j];++j)
if ((*this)[i+j]!=toFind[j])
break;
// if strings were identical then we're done
if (toFind[j]==0)
return i;
}
return i;
}
// return true if this contains given sub string
bool contains(const char *toFind) const
{
return find(toFind)!=size();
}
// a couple of handy atoi routines...
template <class C> bool atoi(C& result) const
{
result=::atoi(c_str());
return (result!=0 || *this=="0");
}
unsigned atoi() const
{
return ::atoi(c_str());
}
// a couple of handy atof routines...
template <class C> bool atof(C& result) const
{
result=::atof(c_str());
return (result!=0 || *this=="0");
}
double atof() const
{
return ::atof(c_str());
}
// case insensitive string compare
bool operator==(const std::string &other) const
{
return stricmp(c_str(),other.c_str())==0;
}
// case insesnsitive string compare
bool operator!=(const std::string &other) const
{
return !(*this==other);
}
};
#endif