前面都已经讲了怎么请HGE支持并显示中文..
另外呢.我们还需要的一个处理字符串的类..
当然也可以不用.所以放到最后拿出来.
不过当对于UNICODE与非UNICODE之间切来切去的时候.
你不可能一直在那里改代码..
这个时候CString就可以用到了.
虽然CString可以放到HGE里使用.不过还是自己找一份比较好/
CString属于ATL的东西.自然会引入ATL的东西.编译时候会填加几十K上百K.
所有还是自己找一份或者自己定一份好..
为此我将Nebula2的nString给放到HGE里去了.
这样也便玩我们使用.
代码如下:仅一个H文件,所有代码都在里面:
// Add by ShowLong. 20070629
// Add from nebula2
#include "hge.h"
#include <ctype.h>
#include <stdarg.h>
#include <cstdarg>
#include < string.h>
#include <assert.h>
#include <malloc.h>
#include <stdio.h>
#include <stdlib.h>
#define t_max(a,b) (((a) > (b)) ? (a) : (b))
#define t_min(a,b) (((a) < (b)) ? (a) : (b))
// ------------------------------------------------------------------------------
class hgeString
{
public:
/// constructor
hgeString();
/// constructor 1
hgeString( const char* str);
/// copy constructor
hgeString( const hgeString& rhs);
/// destructor
~hgeString();
/// = operator
hgeString& operator=( const hgeString& rhs);
/// = operator with string
hgeString& operator=( const char* rhs);
/// += operator with char*
hgeString& operator+=( const char* rhs);
/// += operator with string
hgeString& operator+=( const hgeString& rhs);
/// Is `a' equal to `b'?
friend bool operator == ( const hgeString& a, const hgeString& b);
/// Is `a' unequal to `b'?
friend bool operator != ( const hgeString& a, const hgeString& b);
/// Is `a' smaller than `b'?
friend bool operator < ( const hgeString& a, const hgeString& b);
/// Is `a' greater than `b'?
friend bool operator > ( const hgeString& a, const hgeString& b);
/// Is `a' smaller than or equal to `b'?
friend bool operator <= ( const hgeString& a, const hgeString& b);
/// Is `a' greater than or equal to `b'?
friend bool operator >= ( const hgeString& a, const hgeString& b);
/// Subscript operator (read only).
char operator[]( int i) const;
/// Subscript operator (writable).
char& operator[]( int i);
/// set as char ptr, with explicit length
void Set( const char* ptr, int length);
/// set as char ptr
void Set( const char* str);
/// set as int value
void SetInt( int val);
/// set as float value
void SetFloat( float val);
/// set as bool value
void SetBool( bool val);
/// get string as char ptr
const char* Get() const;
/// return contents as integer
int AsInt() const;
/// return contents as float
float AsFloat() const;
/// return contents as bool
bool AsBool() const;
/// return true if the content is a valid integer
bool IsValidInt() const;
/// return true if the content is a valid float
bool IsValidFloat() const;
/// return true if the content is a valid bool
bool IsValidBool() const;
/// return length of string
int Length() const;
/// clear the string
void Clear();
/// return true if string object is empty
bool IsEmpty() const;
/// return true if string object is not empty
bool IsValid() const;
/// append character pointer
void Append( const char* str);
/// append string
void Append( const hgeString& str);
/// append a range of characters
void AppendRange( const char* str, unsigned int numChars);
/// append int value
void AppendInt( int val);
/// append float value
void AppendFloat( float val);
/// convert string to lower case
void ToLower();
/// convert string to upper case
void ToUpper();
/// *** OBSOLETE *** get first token (this will destroy the string)
const char* GetFirstToken( const char* whiteSpace);
/// *** OBSOLETE *** get next token (this will destroy the string)
const char* GetNextToken( const char* whiteSpace);
/// extract substring
hgeString ExtractRange( int from, int numChars) const;
/// terminate string at first occurrence of character in set
void Strip( const char* charSet);
/// Index of first appearance of `v' starting from index `startIndex'.
int FindStringIndex( const hgeString& v, int startIndex) const;
/// return index of character in string
int FindCharIndex(unsigned char c, int startIndex) const;
/// terminate string at given index
void TerminateAtIndex( int index);
/// returns true if string contains character from set
bool ContainsCharFromSet( const char* charSet) const;
/// strip slash at end of path, if exists
void StripTrailingSlash();
/// delete characters from charset at left side of string
hgeString TrimLeft( const char* charSet) const;
/// delete characters from charset at right side of string
hgeString TrimRight( const char* charSet) const;
/// trim characters from charset at both sides of string
hgeString Trim( const char* charSet) const;
/// substitute every occurrence of a string with another string
hgeString Substitute( const char* str, const char* substStr) const;
/// substitute every occurrence of a character with another character
void SubstituteCharacter( char c, char subst);
/// convert string in place from UTF-8 to 8-bit ANSI
void UTF8toANSI();
/// convert ANSI to UTF-8 in place
void ANSItoUTF8();
/// get pointer to extension (without the dot)
const char* GetExtension() const;
/// check if extension matches (no dot in the extension!)
bool CheckExtension( const char* ext) const;
/// convert backslashes to slashes
void ConvertBackslashes();
/// remove extension
void StripExtension();
/// extract the part after the last directory separator
hgeString ExtractFileName() const;
/// extract the last directory of the path
hgeString ExtractLastDirName() const;
/// extract the part before the last directory separator
hgeString ExtractDirName() const;
/// extract path until last slash
hgeString ExtractToLastSlash() const;
/// format string printf-style
void __cdecl Format( const char* fmtString, ...);
// __attribute__((format(printf,2,3)));
/// format string printf-style, taking a va_list
void FormatWithArgs( const char* fmtString, va_list args);
/// replace illegal filename characters
void ReplaceIllegalFilenameChars( char replacement);
/// return true if string only contains characters from charSet argument
bool CheckValidCharSet( const hgeString& charSet) const;
/// replace characters within a string
void ReplaceChars( const char* charSet, char replacement);
/// construct a string from an int
static hgeString FromInt( int i);
/// construct a string from a float
static hgeString FromFloat( float f);
/// construct a string from a bool
static hgeString FromBool( bool b);
protected:
/// copy contents
void Copy( const hgeString& src);
/// delete contents
void Delete();
/// get pointer to last directory separator
char* GetLastSlash() const;
/// Set the length, accounting for the union.
void SetLength(size_t);
enum
{
LOCALSTRINGSIZE = 14,
};
char* string;
union
{
struct
{
char localString[LOCALSTRINGSIZE];
unsigned short localStrLen;
};
unsigned int strLen;
};
};
// ------------------------------------------------------------------------------
/* *
*/
inline
hgeString::hgeString() :
string(0),
strLen(0),
localStrLen(0)
{
}
// ------------------------------------------------------------------------------
/* *
*/
inline
void
hgeString::Delete()
{
if ( this-> string)
{
delete [] this-> string;
this-> string = 0;
}
this->localString[0] = 0;
this->localStrLen = 0;
}
// ------------------------------------------------------------------------------
/* *
*/
inline
hgeString::~hgeString()
{
this->Delete();
}
// ------------------------------------------------------------------------------
/* *
*/
inline
void
hgeString::Set( const char* str, int length)
{
this->Delete();
if (str)
{
if (length >= LOCALSTRINGSIZE)
{
this-> string = new char[length + 1];
memcpy( this-> string, str, length);
this-> string[length] = 0;
this->strLen = length;
}
else
{
memcpy( this->localString, str, length);
this->localString[length] = 0;
this->localStrLen = (unsigned short)length;
}
}
}
// ------------------------------------------------------------------------------
/* *
*/
inline
void
hgeString::Set( const char* str)
{
int len = 0;
if (str)
{
len = ( int) strlen(str);
}
this->Set(str, len);
}
// ------------------------------------------------------------------------------
/* *
*/
inline
void
hgeString::SetInt( int val)
{
this->Format("%d", val);
}
// ------------------------------------------------------------------------------
/* *
*/
inline
void
hgeString::SetFloat( float val)
{
this->Format("%.6f", val);
}
// ------------------------------------------------------------------------------
/* *
*/
inline
void
hgeString::SetBool( bool val)
{
if (val)
{
* this = "true";
}
else
{
* this = "false";
}
}
// ------------------------------------------------------------------------------
/* *
*/
inline
void
hgeString::Copy( const hgeString& src)
{
assert(0 == this-> string);
const char* str = src.Get();
if (str)
{
this->Set(str);
}
}
// ------------------------------------------------------------------------------
/* *
*/
inline
hgeString::hgeString( const char* str) :
string(0),
strLen(0),
localStrLen(0)
{
this->Set(str);
}
// ------------------------------------------------------------------------------
/* *
*/
inline
hgeString::hgeString( const hgeString& rhs) :
string(0),
strLen(0)
{
this->localString[0] = 0;
this->Copy(rhs);
}
// ------------------------------------------------------------------------------
/* *
*/
inline
const char*
hgeString::Get() const
{
if ( this-> string)
{
return this-> string;
}
if ( this->localString[0])
{
return this->localString;
}
return "";
}
// ------------------------------------------------------------------------------
/* *
*/
inline
hgeString&
hgeString:: operator=( const hgeString& rhs)
{
if (&rhs != this)
{
this->Delete();
this->Copy(rhs);
}
return * this;
}
// ------------------------------------------------------------------------------
/* *
*/
inline
hgeString&
hgeString:: operator=( const char* rhs)
{
if (rhs != this->Get())
{
this->Set(rhs);
}
return * this;
}
// ------------------------------------------------------------------------------
/* *
*/
inline
void
hgeString::AppendRange( const char* str, unsigned int numChars)
{
assert(str);
if (numChars > 0)
{
unsigned int rlen = numChars;
unsigned int tlen = this->Length() + rlen;
if ( this-> string)
{
char* ptr = new char[tlen + 1];
strcpy(ptr, this-> string);
strncat(ptr, str, numChars);
delete [] this-> string;
this-> string = ptr;
this->strLen = tlen;
}
else if ( this->localString[0])
{
if (tlen >= LOCALSTRINGSIZE)
{
char* ptr = new char[tlen + 1];
strcpy(ptr, this->localString);
strncat(ptr, str, numChars);
this->localString[0] = 0;
this-> string = ptr;
this->strLen = tlen;
}
else
{
strncat( this->localString, str, numChars);
this->localStrLen = (unsigned short)tlen;
}
}
else
{
this->Set(str, numChars);
}
}
}
// ------------------------------------------------------------------------------
/* *
*/
inline
void
hgeString::Append( const char* str)
{
assert(str);
unsigned int rlen = (unsigned int)strlen(str);
this->AppendRange(str, rlen);
}
// ------------------------------------------------------------------------------
/* *
*/
inline
void
hgeString::Append( const hgeString& str)
{
this->Append(str.Get());
}
// ------------------------------------------------------------------------------
/* *
*/
inline
void
hgeString::AppendInt( int val)
{
hgeString str;
str.SetInt(val);
this->Append(str);
}
// ------------------------------------------------------------------------------
/* *
*/
inline
void
hgeString::AppendFloat( float val)
{
hgeString str;
str.SetFloat(val);
this->Append(str);
}
// ------------------------------------------------------------------------------
/* *
*/
inline
hgeString&
hgeString:: operator+=( const char* rhs)
{
this->Append(rhs);
return * this;
}
// ------------------------------------------------------------------------------
/* *
*/
inline
hgeString&
hgeString:: operator+=( const hgeString& rhs)
{
this->Append(rhs.Get());
return * this;
}
// ------------------------------------------------------------------------------
/* *
*/
inline
bool
operator == ( const hgeString& a, const hgeString& b)
{
return strcmp(a.Get(), b.Get()) == 0;
}
// ------------------------------------------------------------------------------
/* *
*/
inline
bool
operator != ( const hgeString& a, const hgeString& b)
{
return strcmp(a.Get(), b.Get()) != 0;
}
// ------------------------------------------------------------------------------
/* *
*/
inline
bool
operator < ( const hgeString& a, const hgeString& b)
{
return strcmp(a.Get(), b.Get()) < 0;
}
// ------------------------------------------------------------------------------
/* *
*/
inline
bool
operator > ( const hgeString& a, const hgeString& b)
{
return strcmp(a.Get(), b.Get()) > 0;
}
// ------------------------------------------------------------------------------
/* *
*/
inline
bool
operator <= ( const hgeString& a, const hgeString& b)
{
return strcmp(a.Get(), b.Get()) <= 0;
}
// ------------------------------------------------------------------------------
/* *
*/
inline
bool
operator >= ( const hgeString& a, const hgeString& b)
{
return strcmp(a.Get(), b.Get()) >= 0;
}
// ------------------------------------------------------------------------------
/* *
- 21-Sep-04 Johannes the '/0' is a valid part of the string
*/
inline
char
hgeString:: operator[]( int i) const
{
assert(0 <= i && i <= this->Length());
if ( this-> string != 0)
{
return this-> string[i];
}
return this->localString[i];
}
// ------------------------------------------------------------------------------
/* *
- 21-Sep-04 Johannes the '/0' is a valid part of the string
*/
inline
char&
hgeString:: operator[]( int i)
{
assert(0 <= i && i <= this->Length());
if ( this-> string != 0)
{
return this-> string[i];
}
else
{
return this->localString[i];
}
}
// ------------------------------------------------------------------------------
/* *
*/
inline
int
hgeString::Length() const
{
if ( this-> string != 0)
{
return this->strLen;
}
return this->localStrLen;
}
// ------------------------------------------------------------------------------
/* *
*/
inline
void
hgeString::Clear()
{
this->Delete();
}
// ------------------------------------------------------------------------------
/* *
*/
inline
bool
hgeString::IsEmpty() const
{
if ( this-> string && ( this-> string[0] != 0))
{
return false;
}
if ( this->localString[0] != 0)
{
return false;
}
return true;
}
// ------------------------------------------------------------------------------
/* *
*/
inline
bool
hgeString::IsValid() const
{
return ! this->IsEmpty();
}
// ------------------------------------------------------------------------------
/* *
*/
inline
void
hgeString::ToLower()
{
char* str = ( char*)( this-> string ? this-> string : this->localString);
if (str)
{
char c;
char* ptr = ( char*)str;
while ((c = *ptr))
{
*ptr++ = tolower(c);
}
}
}
// ------------------------------------------------------------------------------
/* *
*/
inline
void
hgeString::ToUpper()
{
char* str = ( char*)( this-> string ? this-> string : this->localString);
if (str)
{
char c;
char* ptr = ( char*)str;
while ((c = *ptr))
{
*ptr++ = toupper(c);
}
}
}
// ------------------------------------------------------------------------------
/* *
*/
static
inline
hgeString
operator+( const hgeString& s0, const hgeString& s1)
{
hgeString newString = s0;
newString.Append(s1.Get());
return newString;
}
// ------------------------------------------------------------------------------
/* *
Get the first token in the string, delimited by one or more of the
character in 'whiteSpace'. This simply invokes the strtok() function
internally, and will destroy the contained string. After calling
GetFirstToken(), invoke GetNextToken() until 0 returns.
ATTENTION: if somebody else calls strtok() while GetFirstToken()/
GetNextToken() is underway, everything will break apart!
Check out the Tokenize() method for a better alternative.
@param whiteSpace string containing white space characters
*/
inline
const char*
hgeString::GetFirstToken( const char* whiteSpace)
{
assert(whiteSpace);
return strtok(( char*) this->Get(), whiteSpace);
}
// ------------------------------------------------------------------------------
/* *
Get the next token in the string. Call this after a GetFirstToken()
or GetNextToken(). Returns 0 if no more tokens in string. This method
will destroy the original string.
ATTENTION: if somebody else calls strtok() while GetFirstToken()/
GetNextToken() is underway, everything will break apart!
Check out the Tokenize() method for a better alternative.
@param whiteSpace string containing whitespace characters
*/
inline
const char*
hgeString::GetNextToken( const char* whiteSpace)
{
assert(whiteSpace);
return strtok(0, whiteSpace);
}
// ------------------------------------------------------------------------------
/* *
Extract sub string.
*/
inline
hgeString
hgeString::ExtractRange( int from, int numChars) const
{
assert(from <= this->Length());
assert(from + numChars <= this->Length());
const char* str = this->Get();
hgeString newString;
newString.Set(&(str[from]), numChars);
return newString;
}
// ------------------------------------------------------------------------------
/* *
Terminates the string at the first occurrence of one of the characters
in charSet.
*/
inline
void
hgeString::Strip( const char* charSet)
{
assert(charSet);
char* str = ( char*) this->Get();
char* ptr = strpbrk(str, charSet);
if (ptr)
{
*ptr = 0;
}
this->SetLength(strlen(str));
}
// ------------------------------------------------------------------------------
/* *
Returns true if string contains one of the characters from charset.
*/
inline
bool
hgeString::ContainsCharFromSet( const char* charSet) const
{
assert(charSet);
char* str = ( char*) this->Get();
char* ptr = strpbrk(str, charSet);
return (0 != ptr);
}
// ------------------------------------------------------------------------------
/* *
@result Index or -1 if not found.
*/
inline
int
hgeString::FindStringIndex( const hgeString& v, int startIndex) const
{
assert(0 <= startIndex && startIndex <= Length() - 1);
assert(!v.IsEmpty());
for ( int i = startIndex; i < Length(); i++)
{
if (Length() - i < v.Length())
{
break;
}
if (strncmp(&(Get()[i]), v.Get(), v.Length()) == 0)
{
return i;
}
}
return -1;
}
// ------------------------------------------------------------------------------
/* *
Return index of character in string, or -1 if not found.
*/
inline
int
hgeString::FindCharIndex(unsigned char c, int startIndex) const
{
if ( this->Length() > 0)
{
assert(startIndex < this->Length());
const char* ptr = strchr( this->Get() + startIndex, c);
if (ptr)
{
return ( int)(ptr - this->Get());
}
}
return -1;
}
// ------------------------------------------------------------------------------
/* *
Terminates the string at the given index.
*/
inline
void
hgeString::TerminateAtIndex( int index)
{
assert(index < this->Length());
char* ptr = ( char*) this->Get();
ptr[index] = 0;
this->SetLength(strlen( this->Get()));
}
// ------------------------------------------------------------------------------
/* *
Strips last slash, if the path name ends on a slash.
*/
inline
void
hgeString::StripTrailingSlash()
{
if ( this->Length() > 0)
{
int pos = Length() - 1;
char* str = ( char*) this->Get();
if (str[pos] == '/' || str[pos] == '/')
{
str[pos] = 0;
if ( this-> string != 0)
{
this->strLen--;
}
else
{
this->localStrLen--;
}
}
this->SetLength(strlen( this->Get()));
}
}
// ------------------------------------------------------------------------------
/* *
Returns a new string which is this string, stripped on the left side
by all characters in the char set.
*/
inline
hgeString
hgeString::TrimLeft( const char* charSet) const
{
assert(charSet);
if ( this->IsEmpty())
{
return * this;
}
int charSetLen = ( int)strlen(charSet);
int thisIndex = 0;
bool stopped = false;
while (!stopped && (thisIndex < this->Length()))
{
int charSetIndex;
bool match = false;
for (charSetIndex = 0; charSetIndex < charSetLen; charSetIndex++)
{
if ((* this)[thisIndex] == charSet[charSetIndex])
{
// a match
match = true;
break;
}
}
if (!match)
{
// stop if no match
stopped = true;
}
else
{
// a match, advance to next character
++thisIndex;
}
}
hgeString trimmedString(&( this->Get()[thisIndex]));
return trimmedString;
}
// ------------------------------------------------------------------------------
/* *
Returns a new string, which is this string, stripped on the right side
by all characters in the char set.
*/
inline
hgeString
hgeString::TrimRight( const char* charSet) const
{
assert(charSet);
if ( this->IsEmpty())
{
return * this;
}
int charSetLen = ( int)strlen(charSet);
int thisIndex = this->Length() - 1;
bool stopped = false;
while (!stopped && (thisIndex < this->Length()))
{
int charSetIndex;
bool match = false;
for (charSetIndex = 0; charSetIndex < charSetLen; charSetIndex++)
{
if ((* this)[thisIndex] == charSet[charSetIndex])
{
// a match
match = true;
break;
}
}
if (!match)
{
// stop if no match
stopped = true;
}
else
{
// a match, advance to next character
--thisIndex;
}
}
hgeString trimmedString;
trimmedString.Set( this->Get(), thisIndex + 1);
return trimmedString;
}
// ------------------------------------------------------------------------------
/* *
Trim both sides of a string.
*/
inline
hgeString
hgeString::Trim( const char* charSet) const
{
return this->TrimLeft(charSet).TrimRight(charSet);
}
// ------------------------------------------------------------------------------
/* *
Substitute every occurrence of origStr with substStr.
*/
inline
hgeString
hgeString::Substitute( const char* matchStr, const char* substStr) const
{
assert(matchStr && substStr);
const char* ptr = this->Get();
int matchStrLen = ( int)strlen(matchStr);
hgeString dest;
// walk original string for occurrences of str
const char* occur;
while ((occur = strstr(ptr, matchStr)))
{
// append string fragment until match
dest.AppendRange(ptr, (unsigned int)(occur - ptr));
// append replacement string
dest.Append(substStr);
// adjust source pointer
ptr = occur + matchStrLen;
}
dest.Append(ptr);
return dest;
}
// ------------------------------------------------------------------------------
/* *
This converts an UTF-8 string to 8-bit-ANSI. Note that only characters
in the range 0 .. 255 are converted, all other characters will be converted
to a question mark.
For conversion rules see http://www.cl.cam.ac.uk/ ~mgk25/unicode.html#utf-8
*/
inline
void
hgeString::UTF8toANSI()
{
unsigned char* src = (unsigned char*) this->Get();
unsigned char* dst = src;
unsigned char c;
while ((c = *src++))
{
if (c >= 0x80)
{
if ((c & 0xE0) == 0xC0)
{
// a 2 byte sequence with 11 bits of information
unsigned short wide = ((c & 0x1F) << 6) | (*src++ & 0x3F);
if (wide > 0xff)
{
c = '?';
}
else
{
c = (unsigned char) wide;
}
}
else if ((c & 0xF0) == 0xE0)
{
// a 3 byte sequence with 16 bits of information
c = '?';
src += 2;
}
else if ((c & 0xF8) == 0xF0)
{
// a 4 byte sequence with 21 bits of information
c = '?';
src += 3;
}
else if ((c & 0xFC) == 0xF8)
{
// a 5 byte sequence with 26 bits of information
c = '?';
src += 4;
}
else if ((c & 0xFE) == 0xFC)
{
// a 6 byte sequence with 31 bits of information
c = '?';
src += 5;
}
}
*dst++ = c;
}
*dst = 0;
}
// ------------------------------------------------------------------------------
/* *
Convert contained ANSI string to UTF-8 in place.
*/
inline
void
hgeString::ANSItoUTF8()
{
assert(! this->IsEmpty());
int bufSize = this->Length() * 2 + 1;
char* buffer = new char[bufSize];
char* dstPtr = buffer;
const char* srcPtr = this->Get();
unsigned char c;
while ((c = *srcPtr++))
{
// note: this only covers the 2 cases that the character
// is between 0 and 127 and between 128 and 255
if (c < 128)
{
*dstPtr++ = c;
}
else
{
*dstPtr++ = 192 + (c / 64);
*dstPtr++ = 128 + (c % 64);
}
}
*dstPtr = 0;
this->Set(buffer);
delete []buffer;
}
// ------------------------------------------------------------------------------
/* *
Replace character with another.
*/
inline
void
hgeString::SubstituteCharacter( char c, char subst)
{
char* ptr = ( char*) this->Get();
int i;
for (i = 0; i <= this->Length(); i++)
{
if (ptr[i] == c)
{
ptr[i] = subst;
}
}
}
// ------------------------------------------------------------------------------
/* *
Converts backslashes to slashes.
*/
inline
void
hgeString::ConvertBackslashes()
{
this->SubstituteCharacter('/', '/');
}
// ------------------------------------------------------------------------------
/* *
@return pointer to extension (without the dot), or 0
*/
inline
const char*
hgeString::GetExtension() const
{
const char* str = this->Get();
const char* ext = strrchr(str, '.');
if (ext)
{
ext++;
if (ext[0] != 0)
{
return ext;
}
}
return 0;
}
// ------------------------------------------------------------------------------
/* *
Returns true if file extension matches.
@param ext extension string (without the dot)
@return true if extension matches
*/
inline
bool
hgeString::CheckExtension( const char* ext) const
{
assert(ext);
const char* extStr = this->GetExtension();
if (0 == extStr)
{
return false;
}
return (0 == (strcmp(ext, extStr)));
}
// ------------------------------------------------------------------------------
/* *
Remove the file extension.
*/
inline
void
hgeString::StripExtension()
{
char* ext = ( char*) this->GetExtension();
if (ext)
{
ext[-1] = 0;
}
this->SetLength(strlen( this->Get()));
}
// ------------------------------------------------------------------------------
/* *
Get a pointer to the last directory separator.
*/
inline
char*
hgeString::GetLastSlash() const
{
char* s = ( char*) this->Get();
char* lastSlash = strrchr(s, '/');
if (0 == lastSlash) lastSlash = strrchr(s, '/');
if (0 == lastSlash) lastSlash = strrchr(s, ':');
return lastSlash;
}
// ------------------------------------------------------------------------------
/* *
Return a hgeString object containing the part after the last
path separator.
*/
inline
hgeString
hgeString::ExtractFileName() const
{
hgeString pathString;
char* lastSlash = this->GetLastSlash();
if (lastSlash)
{
pathString = &(lastSlash[1]);
}
else
{
pathString = this->Get();
}
return pathString;
}
// ------------------------------------------------------------------------------
/* *
Return a hgeString object containing the last directory of the path, i.e.
a category.
- 17-Feb-04 floh fixed a bug when the path ended with a slash
*/
inline
hgeString
hgeString::ExtractLastDirName() const
{
hgeString pathString(* this);
char* lastSlash = pathString.GetLastSlash();
// special case if path ends with a slash
if (lastSlash)
{
if (0 == lastSlash[1])
{
*lastSlash = 0;
lastSlash = pathString.GetLastSlash();
}
char* secLastSlash = 0;
if (0 != lastSlash)
{
*lastSlash = 0; // cut filename
secLastSlash = pathString.GetLastSlash();
if (secLastSlash)
{
*secLastSlash = 0;
return hgeString(secLastSlash+1);
}
}
}
return "";
}
// ------------------------------------------------------------------------------
/* *
Return a hgeString object containing the part before the last
directory separator.
NOTE: I left my fix in that returns the last slash (or colon), this was
necessary to tell if a dirname is a normal directory or an assign.
- 17-Feb-04 floh fixed a bug when the path ended with a slash
*/
inline
hgeString
hgeString::ExtractDirName() const
{
hgeString pathString(* this);
char* lastSlash = pathString.GetLastSlash();
// special case if path ends with a slash
if (lastSlash)
{
if (0 == lastSlash[1])
{
*lastSlash = 0;
lastSlash = pathString.GetLastSlash();
}
if (lastSlash)
{
*++lastSlash = 0;
}
}
pathString.SetLength(strlen(pathString.Get()));
return pathString;
}
// ------------------------------------------------------------------------------
/* *
Return a path string object which contains of the complete path
up to the last slash. Returns an empty string if there is no
slash in the path.
*/
inline
hgeString
hgeString::ExtractToLastSlash() const
{
hgeString pathString(* this);
char* lastSlash = pathString.GetLastSlash();
if (lastSlash)
{
lastSlash[1] = 0;
}
else
{
pathString = "";
}
return pathString;
}
// ------------------------------------------------------------------------------
/* *
*/
inline
void
hgeString::ReplaceChars( const char* charSet, char replacement)
{
assert(charSet);
char* ptr = ( char*) this->Get();
char c;
while (0 != (c = *ptr))
{
if (strchr(charSet, c))
{
*ptr = replacement;
}
ptr++;
}
}
// ------------------------------------------------------------------------------
/* *
Return true if the string only contains characters which are in the defined
character set.
*/
inline
bool
hgeString::CheckValidCharSet( const hgeString& charSet) const
{
int i;
int len = this->Length();
for (i = 0; i < len; i++)
{
if (-1 == charSet.FindCharIndex((* this)[i], 0))
{
return false;
}
}
return true;
}
// ------------------------------------------------------------------------------
/* *
*/
inline
bool
hgeString::IsValidInt() const
{
return this->CheckValidCharSet(" -+01234567890");
}
// ------------------------------------------------------------------------------
/* *
Note: this method is not 100% correct, it just checks for invalid characters.
*/
inline
bool
hgeString::IsValidFloat() const
{
return this->CheckValidCharSet(" -+.e1234567890");
}
// ------------------------------------------------------------------------------
/* *
*/
inline
bool
hgeString::IsValidBool() const
{
static const char* bools[] = {
"no", "yes", "off", "on", "false", "true", 0
};
int i = 0;
while (bools[i] != 0)
{
if (0 == stricmp(bools[i], this->Get()))
{
return true;
}
i++;
}
return false;
}
// ------------------------------------------------------------------------------
/* *
Returns content as integer. Note: this method doesn't check whether the
contents is actually a valid integer. Use the IsValidInteger() method
for this!
*/
inline
int
hgeString::AsInt() const
{
return atoi( this->Get());
}
// ------------------------------------------------------------------------------
/* *
Returns content as float. Note: this method doesn't check whether the
contents is actually a valid float. Use the IsValidInt() method
for this!
*/
inline
float
hgeString::AsFloat() const
{
return float(atof( this->Get()));
}
// ------------------------------------------------------------------------------
/* *
*/
inline
bool
hgeString::AsBool() const
{
static const char* bools[] = {
"no", "yes", "off", "on", "false", "true", 0
};
int i = 0;
while (bools[i] != 0)
{
if (0 == stricmp(bools[i], this->Get()))
{
return 1 == (i & 1);
}
i++;
}
return false;
}
// ------------------------------------------------------------------------------
/* *
*/
inline
void __cdecl
hgeString::Format( const char* fmtString, ...)
{
va_list argList;
va_start(argList, fmtString);
this->FormatWithArgs(fmtString, argList);
va_end(argList);
}
// ------------------------------------------------------------------------------
/* *
*/
inline
void
hgeString::FormatWithArgs( const char* fmtString, va_list args)
{
va_list argList;
// First calculate the required length
argList = args;
size_t requiredLength;
requiredLength = _vscprintf(fmtString, argList);
requiredLength++; // Account for NULL termination
va_end(argList);
// Now we can allocate a buffer of the right length
char* buf = ( char*)alloca(requiredLength);
// Now do the formatting
_vsnprintf(buf, requiredLength, fmtString, args);
this->Set(buf);
}
// ------------------------------------------------------------------------------
/* *
*/
inline
void
hgeString::SetLength(size_t length)
{
if ( this-> string != 0)
{
this->strLen = (unsigned int)length;
}
else
{
this->localStrLen = (unsigned short)length;
}
}
// ------------------------------------------------------------------------------
/* *
*/
inline
void
hgeString::ReplaceIllegalFilenameChars( char replacement)
{
this->ReplaceChars("//:*?"<>|", replacement);
}
// ------------------------------------------------------------------------------
/* *
*/
inline
hgeString
hgeString::FromInt( int i)
{
hgeString str;
str.SetInt(i);
return str;
}
// ------------------------------------------------------------------------------
/* *
*/
inline
hgeString
hgeString::FromFloat( float f)
{
hgeString str;
str.SetFloat(f);
return str;
}
// ------------------------------------------------------------------------------
/* *
*/
inline
hgeString
hgeString::FromBool( bool b)
{
hgeString str;
str.SetBool(b);
return str;
}
#pragma
once
// Add from nebula2
#include "hge.h"
#include <ctype.h>
#include <stdarg.h>
#include <cstdarg>
#include < string.h>
#include <assert.h>
#include <malloc.h>
#include <stdio.h>
#include <stdlib.h>
#define t_max(a,b) (((a) > (b)) ? (a) : (b))
#define t_min(a,b) (((a) < (b)) ? (a) : (b))
// ------------------------------------------------------------------------------
class hgeString
{
public:
/// constructor
hgeString();
/// constructor 1
hgeString( const char* str);
/// copy constructor
hgeString( const hgeString& rhs);
/// destructor
~hgeString();
/// = operator
hgeString& operator=( const hgeString& rhs);
/// = operator with string
hgeString& operator=( const char* rhs);
/// += operator with char*
hgeString& operator+=( const char* rhs);
/// += operator with string
hgeString& operator+=( const hgeString& rhs);
/// Is `a' equal to `b'?
friend bool operator == ( const hgeString& a, const hgeString& b);
/// Is `a' unequal to `b'?
friend bool operator != ( const hgeString& a, const hgeString& b);
/// Is `a' smaller than `b'?
friend bool operator < ( const hgeString& a, const hgeString& b);
/// Is `a' greater than `b'?
friend bool operator > ( const hgeString& a, const hgeString& b);
/// Is `a' smaller than or equal to `b'?
friend bool operator <= ( const hgeString& a, const hgeString& b);
/// Is `a' greater than or equal to `b'?
friend bool operator >= ( const hgeString& a, const hgeString& b);
/// Subscript operator (read only).
char operator[]( int i) const;
/// Subscript operator (writable).
char& operator[]( int i);
/// set as char ptr, with explicit length
void Set( const char* ptr, int length);
/// set as char ptr
void Set( const char* str);
/// set as int value
void SetInt( int val);
/// set as float value
void SetFloat( float val);
/// set as bool value
void SetBool( bool val);
/// get string as char ptr
const char* Get() const;
/// return contents as integer
int AsInt() const;
/// return contents as float
float AsFloat() const;
/// return contents as bool
bool AsBool() const;
/// return true if the content is a valid integer
bool IsValidInt() const;
/// return true if the content is a valid float
bool IsValidFloat() const;
/// return true if the content is a valid bool
bool IsValidBool() const;
/// return length of string
int Length() const;
/// clear the string
void Clear();
/// return true if string object is empty
bool IsEmpty() const;
/// return true if string object is not empty
bool IsValid() const;
/// append character pointer
void Append( const char* str);
/// append string
void Append( const hgeString& str);
/// append a range of characters
void AppendRange( const char* str, unsigned int numChars);
/// append int value
void AppendInt( int val);
/// append float value
void AppendFloat( float val);
/// convert string to lower case
void ToLower();
/// convert string to upper case
void ToUpper();
/// *** OBSOLETE *** get first token (this will destroy the string)
const char* GetFirstToken( const char* whiteSpace);
/// *** OBSOLETE *** get next token (this will destroy the string)
const char* GetNextToken( const char* whiteSpace);
/// extract substring
hgeString ExtractRange( int from, int numChars) const;
/// terminate string at first occurrence of character in set
void Strip( const char* charSet);
/// Index of first appearance of `v' starting from index `startIndex'.
int FindStringIndex( const hgeString& v, int startIndex) const;
/// return index of character in string
int FindCharIndex(unsigned char c, int startIndex) const;
/// terminate string at given index
void TerminateAtIndex( int index);
/// returns true if string contains character from set
bool ContainsCharFromSet( const char* charSet) const;
/// strip slash at end of path, if exists
void StripTrailingSlash();
/// delete characters from charset at left side of string
hgeString TrimLeft( const char* charSet) const;
/// delete characters from charset at right side of string
hgeString TrimRight( const char* charSet) const;
/// trim characters from charset at both sides of string
hgeString Trim( const char* charSet) const;
/// substitute every occurrence of a string with another string
hgeString Substitute( const char* str, const char* substStr) const;
/// substitute every occurrence of a character with another character
void SubstituteCharacter( char c, char subst);
/// convert string in place from UTF-8 to 8-bit ANSI
void UTF8toANSI();
/// convert ANSI to UTF-8 in place
void ANSItoUTF8();
/// get pointer to extension (without the dot)
const char* GetExtension() const;
/// check if extension matches (no dot in the extension!)
bool CheckExtension( const char* ext) const;
/// convert backslashes to slashes
void ConvertBackslashes();
/// remove extension
void StripExtension();
/// extract the part after the last directory separator
hgeString ExtractFileName() const;
/// extract the last directory of the path
hgeString ExtractLastDirName() const;
/// extract the part before the last directory separator
hgeString ExtractDirName() const;
/// extract path until last slash
hgeString ExtractToLastSlash() const;
/// format string printf-style
void __cdecl Format( const char* fmtString, ...);
// __attribute__((format(printf,2,3)));
/// format string printf-style, taking a va_list
void FormatWithArgs( const char* fmtString, va_list args);
/// replace illegal filename characters
void ReplaceIllegalFilenameChars( char replacement);
/// return true if string only contains characters from charSet argument
bool CheckValidCharSet( const hgeString& charSet) const;
/// replace characters within a string
void ReplaceChars( const char* charSet, char replacement);
/// construct a string from an int
static hgeString FromInt( int i);
/// construct a string from a float
static hgeString FromFloat( float f);
/// construct a string from a bool
static hgeString FromBool( bool b);
protected:
/// copy contents
void Copy( const hgeString& src);
/// delete contents
void Delete();
/// get pointer to last directory separator
char* GetLastSlash() const;
/// Set the length, accounting for the union.
void SetLength(size_t);
enum
{
LOCALSTRINGSIZE = 14,
};
char* string;
union
{
struct
{
char localString[LOCALSTRINGSIZE];
unsigned short localStrLen;
};
unsigned int strLen;
};
};
// ------------------------------------------------------------------------------
/* *
*/
inline
hgeString::hgeString() :
string(0),
strLen(0),
localStrLen(0)
{
}
// ------------------------------------------------------------------------------
/* *
*/
inline
void
hgeString::Delete()
{
if ( this-> string)
{
delete [] this-> string;
this-> string = 0;
}
this->localString[0] = 0;
this->localStrLen = 0;
}
// ------------------------------------------------------------------------------
/* *
*/
inline
hgeString::~hgeString()
{
this->Delete();
}
// ------------------------------------------------------------------------------
/* *
*/
inline
void
hgeString::Set( const char* str, int length)
{
this->Delete();
if (str)
{
if (length >= LOCALSTRINGSIZE)
{
this-> string = new char[length + 1];
memcpy( this-> string, str, length);
this-> string[length] = 0;
this->strLen = length;
}
else
{
memcpy( this->localString, str, length);
this->localString[length] = 0;
this->localStrLen = (unsigned short)length;
}
}
}
// ------------------------------------------------------------------------------
/* *
*/
inline
void
hgeString::Set( const char* str)
{
int len = 0;
if (str)
{
len = ( int) strlen(str);
}
this->Set(str, len);
}
// ------------------------------------------------------------------------------
/* *
*/
inline
void
hgeString::SetInt( int val)
{
this->Format("%d", val);
}
// ------------------------------------------------------------------------------
/* *
*/
inline
void
hgeString::SetFloat( float val)
{
this->Format("%.6f", val);
}
// ------------------------------------------------------------------------------
/* *
*/
inline
void
hgeString::SetBool( bool val)
{
if (val)
{
* this = "true";
}
else
{
* this = "false";
}
}
// ------------------------------------------------------------------------------
/* *
*/
inline
void
hgeString::Copy( const hgeString& src)
{
assert(0 == this-> string);
const char* str = src.Get();
if (str)
{
this->Set(str);
}
}
// ------------------------------------------------------------------------------
/* *
*/
inline
hgeString::hgeString( const char* str) :
string(0),
strLen(0),
localStrLen(0)
{
this->Set(str);
}
// ------------------------------------------------------------------------------
/* *
*/
inline
hgeString::hgeString( const hgeString& rhs) :
string(0),
strLen(0)
{
this->localString[0] = 0;
this->Copy(rhs);
}
// ------------------------------------------------------------------------------
/* *
*/
inline
const char*
hgeString::Get() const
{
if ( this-> string)
{
return this-> string;
}
if ( this->localString[0])
{
return this->localString;
}
return "";
}
// ------------------------------------------------------------------------------
/* *
*/
inline
hgeString&
hgeString:: operator=( const hgeString& rhs)
{
if (&rhs != this)
{
this->Delete();
this->Copy(rhs);
}
return * this;
}
// ------------------------------------------------------------------------------
/* *
*/
inline
hgeString&
hgeString:: operator=( const char* rhs)
{
if (rhs != this->Get())
{
this->Set(rhs);
}
return * this;
}
// ------------------------------------------------------------------------------
/* *
*/
inline
void
hgeString::AppendRange( const char* str, unsigned int numChars)
{
assert(str);
if (numChars > 0)
{
unsigned int rlen = numChars;
unsigned int tlen = this->Length() + rlen;
if ( this-> string)
{
char* ptr = new char[tlen + 1];
strcpy(ptr, this-> string);
strncat(ptr, str, numChars);
delete [] this-> string;
this-> string = ptr;
this->strLen = tlen;
}
else if ( this->localString[0])
{
if (tlen >= LOCALSTRINGSIZE)
{
char* ptr = new char[tlen + 1];
strcpy(ptr, this->localString);
strncat(ptr, str, numChars);
this->localString[0] = 0;
this-> string = ptr;
this->strLen = tlen;
}
else
{
strncat( this->localString, str, numChars);
this->localStrLen = (unsigned short)tlen;
}
}
else
{
this->Set(str, numChars);
}
}
}
// ------------------------------------------------------------------------------
/* *
*/
inline
void
hgeString::Append( const char* str)
{
assert(str);
unsigned int rlen = (unsigned int)strlen(str);
this->AppendRange(str, rlen);
}
// ------------------------------------------------------------------------------
/* *
*/
inline
void
hgeString::Append( const hgeString& str)
{
this->Append(str.Get());
}
// ------------------------------------------------------------------------------
/* *
*/
inline
void
hgeString::AppendInt( int val)
{
hgeString str;
str.SetInt(val);
this->Append(str);
}
// ------------------------------------------------------------------------------
/* *
*/
inline
void
hgeString::AppendFloat( float val)
{
hgeString str;
str.SetFloat(val);
this->Append(str);
}
// ------------------------------------------------------------------------------
/* *
*/
inline
hgeString&
hgeString:: operator+=( const char* rhs)
{
this->Append(rhs);
return * this;
}
// ------------------------------------------------------------------------------
/* *
*/
inline
hgeString&
hgeString:: operator+=( const hgeString& rhs)
{
this->Append(rhs.Get());
return * this;
}
// ------------------------------------------------------------------------------
/* *
*/
inline
bool
operator == ( const hgeString& a, const hgeString& b)
{
return strcmp(a.Get(), b.Get()) == 0;
}
// ------------------------------------------------------------------------------
/* *
*/
inline
bool
operator != ( const hgeString& a, const hgeString& b)
{
return strcmp(a.Get(), b.Get()) != 0;
}
// ------------------------------------------------------------------------------
/* *
*/
inline
bool
operator < ( const hgeString& a, const hgeString& b)
{
return strcmp(a.Get(), b.Get()) < 0;
}
// ------------------------------------------------------------------------------
/* *
*/
inline
bool
operator > ( const hgeString& a, const hgeString& b)
{
return strcmp(a.Get(), b.Get()) > 0;
}
// ------------------------------------------------------------------------------
/* *
*/
inline
bool
operator <= ( const hgeString& a, const hgeString& b)
{
return strcmp(a.Get(), b.Get()) <= 0;
}
// ------------------------------------------------------------------------------
/* *
*/
inline
bool
operator >= ( const hgeString& a, const hgeString& b)
{
return strcmp(a.Get(), b.Get()) >= 0;
}
// ------------------------------------------------------------------------------
/* *
- 21-Sep-04 Johannes the '/0' is a valid part of the string
*/
inline
char
hgeString:: operator[]( int i) const
{
assert(0 <= i && i <= this->Length());
if ( this-> string != 0)
{
return this-> string[i];
}
return this->localString[i];
}
// ------------------------------------------------------------------------------
/* *
- 21-Sep-04 Johannes the '/0' is a valid part of the string
*/
inline
char&
hgeString:: operator[]( int i)
{
assert(0 <= i && i <= this->Length());
if ( this-> string != 0)
{
return this-> string[i];
}
else
{
return this->localString[i];
}
}
// ------------------------------------------------------------------------------
/* *
*/
inline
int
hgeString::Length() const
{
if ( this-> string != 0)
{
return this->strLen;
}
return this->localStrLen;
}
// ------------------------------------------------------------------------------
/* *
*/
inline
void
hgeString::Clear()
{
this->Delete();
}
// ------------------------------------------------------------------------------
/* *
*/
inline
bool
hgeString::IsEmpty() const
{
if ( this-> string && ( this-> string[0] != 0))
{
return false;
}
if ( this->localString[0] != 0)
{
return false;
}
return true;
}
// ------------------------------------------------------------------------------
/* *
*/
inline
bool
hgeString::IsValid() const
{
return ! this->IsEmpty();
}
// ------------------------------------------------------------------------------
/* *
*/
inline
void
hgeString::ToLower()
{
char* str = ( char*)( this-> string ? this-> string : this->localString);
if (str)
{
char c;
char* ptr = ( char*)str;
while ((c = *ptr))
{
*ptr++ = tolower(c);
}
}
}
// ------------------------------------------------------------------------------
/* *
*/
inline
void
hgeString::ToUpper()
{
char* str = ( char*)( this-> string ? this-> string : this->localString);
if (str)
{
char c;
char* ptr = ( char*)str;
while ((c = *ptr))
{
*ptr++ = toupper(c);
}
}
}
// ------------------------------------------------------------------------------
/* *
*/
static
inline
hgeString
operator+( const hgeString& s0, const hgeString& s1)
{
hgeString newString = s0;
newString.Append(s1.Get());
return newString;
}
// ------------------------------------------------------------------------------
/* *
Get the first token in the string, delimited by one or more of the
character in 'whiteSpace'. This simply invokes the strtok() function
internally, and will destroy the contained string. After calling
GetFirstToken(), invoke GetNextToken() until 0 returns.
ATTENTION: if somebody else calls strtok() while GetFirstToken()/
GetNextToken() is underway, everything will break apart!
Check out the Tokenize() method for a better alternative.
@param whiteSpace string containing white space characters
*/
inline
const char*
hgeString::GetFirstToken( const char* whiteSpace)
{
assert(whiteSpace);
return strtok(( char*) this->Get(), whiteSpace);
}
// ------------------------------------------------------------------------------
/* *
Get the next token in the string. Call this after a GetFirstToken()
or GetNextToken(). Returns 0 if no more tokens in string. This method
will destroy the original string.
ATTENTION: if somebody else calls strtok() while GetFirstToken()/
GetNextToken() is underway, everything will break apart!
Check out the Tokenize() method for a better alternative.
@param whiteSpace string containing whitespace characters
*/
inline
const char*
hgeString::GetNextToken( const char* whiteSpace)
{
assert(whiteSpace);
return strtok(0, whiteSpace);
}
// ------------------------------------------------------------------------------
/* *
Extract sub string.
*/
inline
hgeString
hgeString::ExtractRange( int from, int numChars) const
{
assert(from <= this->Length());
assert(from + numChars <= this->Length());
const char* str = this->Get();
hgeString newString;
newString.Set(&(str[from]), numChars);
return newString;
}
// ------------------------------------------------------------------------------
/* *
Terminates the string at the first occurrence of one of the characters
in charSet.
*/
inline
void
hgeString::Strip( const char* charSet)
{
assert(charSet);
char* str = ( char*) this->Get();
char* ptr = strpbrk(str, charSet);
if (ptr)
{
*ptr = 0;
}
this->SetLength(strlen(str));
}
// ------------------------------------------------------------------------------
/* *
Returns true if string contains one of the characters from charset.
*/
inline
bool
hgeString::ContainsCharFromSet( const char* charSet) const
{
assert(charSet);
char* str = ( char*) this->Get();
char* ptr = strpbrk(str, charSet);
return (0 != ptr);
}
// ------------------------------------------------------------------------------
/* *
@result Index or -1 if not found.
*/
inline
int
hgeString::FindStringIndex( const hgeString& v, int startIndex) const
{
assert(0 <= startIndex && startIndex <= Length() - 1);
assert(!v.IsEmpty());
for ( int i = startIndex; i < Length(); i++)
{
if (Length() - i < v.Length())
{
break;
}
if (strncmp(&(Get()[i]), v.Get(), v.Length()) == 0)
{
return i;
}
}
return -1;
}
// ------------------------------------------------------------------------------
/* *
Return index of character in string, or -1 if not found.
*/
inline
int
hgeString::FindCharIndex(unsigned char c, int startIndex) const
{
if ( this->Length() > 0)
{
assert(startIndex < this->Length());
const char* ptr = strchr( this->Get() + startIndex, c);
if (ptr)
{
return ( int)(ptr - this->Get());
}
}
return -1;
}
// ------------------------------------------------------------------------------
/* *
Terminates the string at the given index.
*/
inline
void
hgeString::TerminateAtIndex( int index)
{
assert(index < this->Length());
char* ptr = ( char*) this->Get();
ptr[index] = 0;
this->SetLength(strlen( this->Get()));
}
// ------------------------------------------------------------------------------
/* *
Strips last slash, if the path name ends on a slash.
*/
inline
void
hgeString::StripTrailingSlash()
{
if ( this->Length() > 0)
{
int pos = Length() - 1;
char* str = ( char*) this->Get();
if (str[pos] == '/' || str[pos] == '/')
{
str[pos] = 0;
if ( this-> string != 0)
{
this->strLen--;
}
else
{
this->localStrLen--;
}
}
this->SetLength(strlen( this->Get()));
}
}
// ------------------------------------------------------------------------------
/* *
Returns a new string which is this string, stripped on the left side
by all characters in the char set.
*/
inline
hgeString
hgeString::TrimLeft( const char* charSet) const
{
assert(charSet);
if ( this->IsEmpty())
{
return * this;
}
int charSetLen = ( int)strlen(charSet);
int thisIndex = 0;
bool stopped = false;
while (!stopped && (thisIndex < this->Length()))
{
int charSetIndex;
bool match = false;
for (charSetIndex = 0; charSetIndex < charSetLen; charSetIndex++)
{
if ((* this)[thisIndex] == charSet[charSetIndex])
{
// a match
match = true;
break;
}
}
if (!match)
{
// stop if no match
stopped = true;
}
else
{
// a match, advance to next character
++thisIndex;
}
}
hgeString trimmedString(&( this->Get()[thisIndex]));
return trimmedString;
}
// ------------------------------------------------------------------------------
/* *
Returns a new string, which is this string, stripped on the right side
by all characters in the char set.
*/
inline
hgeString
hgeString::TrimRight( const char* charSet) const
{
assert(charSet);
if ( this->IsEmpty())
{
return * this;
}
int charSetLen = ( int)strlen(charSet);
int thisIndex = this->Length() - 1;
bool stopped = false;
while (!stopped && (thisIndex < this->Length()))
{
int charSetIndex;
bool match = false;
for (charSetIndex = 0; charSetIndex < charSetLen; charSetIndex++)
{
if ((* this)[thisIndex] == charSet[charSetIndex])
{
// a match
match = true;
break;
}
}
if (!match)
{
// stop if no match
stopped = true;
}
else
{
// a match, advance to next character
--thisIndex;
}
}
hgeString trimmedString;
trimmedString.Set( this->Get(), thisIndex + 1);
return trimmedString;
}
// ------------------------------------------------------------------------------
/* *
Trim both sides of a string.
*/
inline
hgeString
hgeString::Trim( const char* charSet) const
{
return this->TrimLeft(charSet).TrimRight(charSet);
}
// ------------------------------------------------------------------------------
/* *
Substitute every occurrence of origStr with substStr.
*/
inline
hgeString
hgeString::Substitute( const char* matchStr, const char* substStr) const
{
assert(matchStr && substStr);
const char* ptr = this->Get();
int matchStrLen = ( int)strlen(matchStr);
hgeString dest;
// walk original string for occurrences of str
const char* occur;
while ((occur = strstr(ptr, matchStr)))
{
// append string fragment until match
dest.AppendRange(ptr, (unsigned int)(occur - ptr));
// append replacement string
dest.Append(substStr);
// adjust source pointer
ptr = occur + matchStrLen;
}
dest.Append(ptr);
return dest;
}
// ------------------------------------------------------------------------------
/* *
This converts an UTF-8 string to 8-bit-ANSI. Note that only characters
in the range 0 .. 255 are converted, all other characters will be converted
to a question mark.
For conversion rules see http://www.cl.cam.ac.uk/ ~mgk25/unicode.html#utf-8
*/
inline
void
hgeString::UTF8toANSI()
{
unsigned char* src = (unsigned char*) this->Get();
unsigned char* dst = src;
unsigned char c;
while ((c = *src++))
{
if (c >= 0x80)
{
if ((c & 0xE0) == 0xC0)
{
// a 2 byte sequence with 11 bits of information
unsigned short wide = ((c & 0x1F) << 6) | (*src++ & 0x3F);
if (wide > 0xff)
{
c = '?';
}
else
{
c = (unsigned char) wide;
}
}
else if ((c & 0xF0) == 0xE0)
{
// a 3 byte sequence with 16 bits of information
c = '?';
src += 2;
}
else if ((c & 0xF8) == 0xF0)
{
// a 4 byte sequence with 21 bits of information
c = '?';
src += 3;
}
else if ((c & 0xFC) == 0xF8)
{
// a 5 byte sequence with 26 bits of information
c = '?';
src += 4;
}
else if ((c & 0xFE) == 0xFC)
{
// a 6 byte sequence with 31 bits of information
c = '?';
src += 5;
}
}
*dst++ = c;
}
*dst = 0;
}
// ------------------------------------------------------------------------------
/* *
Convert contained ANSI string to UTF-8 in place.
*/
inline
void
hgeString::ANSItoUTF8()
{
assert(! this->IsEmpty());
int bufSize = this->Length() * 2 + 1;
char* buffer = new char[bufSize];
char* dstPtr = buffer;
const char* srcPtr = this->Get();
unsigned char c;
while ((c = *srcPtr++))
{
// note: this only covers the 2 cases that the character
// is between 0 and 127 and between 128 and 255
if (c < 128)
{
*dstPtr++ = c;
}
else
{
*dstPtr++ = 192 + (c / 64);
*dstPtr++ = 128 + (c % 64);
}
}
*dstPtr = 0;
this->Set(buffer);
delete []buffer;
}
// ------------------------------------------------------------------------------
/* *
Replace character with another.
*/
inline
void
hgeString::SubstituteCharacter( char c, char subst)
{
char* ptr = ( char*) this->Get();
int i;
for (i = 0; i <= this->Length(); i++)
{
if (ptr[i] == c)
{
ptr[i] = subst;
}
}
}
// ------------------------------------------------------------------------------
/* *
Converts backslashes to slashes.
*/
inline
void
hgeString::ConvertBackslashes()
{
this->SubstituteCharacter('/', '/');
}
// ------------------------------------------------------------------------------
/* *
@return pointer to extension (without the dot), or 0
*/
inline
const char*
hgeString::GetExtension() const
{
const char* str = this->Get();
const char* ext = strrchr(str, '.');
if (ext)
{
ext++;
if (ext[0] != 0)
{
return ext;
}
}
return 0;
}
// ------------------------------------------------------------------------------
/* *
Returns true if file extension matches.
@param ext extension string (without the dot)
@return true if extension matches
*/
inline
bool
hgeString::CheckExtension( const char* ext) const
{
assert(ext);
const char* extStr = this->GetExtension();
if (0 == extStr)
{
return false;
}
return (0 == (strcmp(ext, extStr)));
}
// ------------------------------------------------------------------------------
/* *
Remove the file extension.
*/
inline
void
hgeString::StripExtension()
{
char* ext = ( char*) this->GetExtension();
if (ext)
{
ext[-1] = 0;
}
this->SetLength(strlen( this->Get()));
}
// ------------------------------------------------------------------------------
/* *
Get a pointer to the last directory separator.
*/
inline
char*
hgeString::GetLastSlash() const
{
char* s = ( char*) this->Get();
char* lastSlash = strrchr(s, '/');
if (0 == lastSlash) lastSlash = strrchr(s, '/');
if (0 == lastSlash) lastSlash = strrchr(s, ':');
return lastSlash;
}
// ------------------------------------------------------------------------------
/* *
Return a hgeString object containing the part after the last
path separator.
*/
inline
hgeString
hgeString::ExtractFileName() const
{
hgeString pathString;
char* lastSlash = this->GetLastSlash();
if (lastSlash)
{
pathString = &(lastSlash[1]);
}
else
{
pathString = this->Get();
}
return pathString;
}
// ------------------------------------------------------------------------------
/* *
Return a hgeString object containing the last directory of the path, i.e.
a category.
- 17-Feb-04 floh fixed a bug when the path ended with a slash
*/
inline
hgeString
hgeString::ExtractLastDirName() const
{
hgeString pathString(* this);
char* lastSlash = pathString.GetLastSlash();
// special case if path ends with a slash
if (lastSlash)
{
if (0 == lastSlash[1])
{
*lastSlash = 0;
lastSlash = pathString.GetLastSlash();
}
char* secLastSlash = 0;
if (0 != lastSlash)
{
*lastSlash = 0; // cut filename
secLastSlash = pathString.GetLastSlash();
if (secLastSlash)
{
*secLastSlash = 0;
return hgeString(secLastSlash+1);
}
}
}
return "";
}
// ------------------------------------------------------------------------------
/* *
Return a hgeString object containing the part before the last
directory separator.
NOTE: I left my fix in that returns the last slash (or colon), this was
necessary to tell if a dirname is a normal directory or an assign.
- 17-Feb-04 floh fixed a bug when the path ended with a slash
*/
inline
hgeString
hgeString::ExtractDirName() const
{
hgeString pathString(* this);
char* lastSlash = pathString.GetLastSlash();
// special case if path ends with a slash
if (lastSlash)
{
if (0 == lastSlash[1])
{
*lastSlash = 0;
lastSlash = pathString.GetLastSlash();
}
if (lastSlash)
{
*++lastSlash = 0;
}
}
pathString.SetLength(strlen(pathString.Get()));
return pathString;
}
// ------------------------------------------------------------------------------
/* *
Return a path string object which contains of the complete path
up to the last slash. Returns an empty string if there is no
slash in the path.
*/
inline
hgeString
hgeString::ExtractToLastSlash() const
{
hgeString pathString(* this);
char* lastSlash = pathString.GetLastSlash();
if (lastSlash)
{
lastSlash[1] = 0;
}
else
{
pathString = "";
}
return pathString;
}
// ------------------------------------------------------------------------------
/* *
*/
inline
void
hgeString::ReplaceChars( const char* charSet, char replacement)
{
assert(charSet);
char* ptr = ( char*) this->Get();
char c;
while (0 != (c = *ptr))
{
if (strchr(charSet, c))
{
*ptr = replacement;
}
ptr++;
}
}
// ------------------------------------------------------------------------------
/* *
Return true if the string only contains characters which are in the defined
character set.
*/
inline
bool
hgeString::CheckValidCharSet( const hgeString& charSet) const
{
int i;
int len = this->Length();
for (i = 0; i < len; i++)
{
if (-1 == charSet.FindCharIndex((* this)[i], 0))
{
return false;
}
}
return true;
}
// ------------------------------------------------------------------------------
/* *
*/
inline
bool
hgeString::IsValidInt() const
{
return this->CheckValidCharSet(" -+01234567890");
}
// ------------------------------------------------------------------------------
/* *
Note: this method is not 100% correct, it just checks for invalid characters.
*/
inline
bool
hgeString::IsValidFloat() const
{
return this->CheckValidCharSet(" -+.e1234567890");
}
// ------------------------------------------------------------------------------
/* *
*/
inline
bool
hgeString::IsValidBool() const
{
static const char* bools[] = {
"no", "yes", "off", "on", "false", "true", 0
};
int i = 0;
while (bools[i] != 0)
{
if (0 == stricmp(bools[i], this->Get()))
{
return true;
}
i++;
}
return false;
}
// ------------------------------------------------------------------------------
/* *
Returns content as integer. Note: this method doesn't check whether the
contents is actually a valid integer. Use the IsValidInteger() method
for this!
*/
inline
int
hgeString::AsInt() const
{
return atoi( this->Get());
}
// ------------------------------------------------------------------------------
/* *
Returns content as float. Note: this method doesn't check whether the
contents is actually a valid float. Use the IsValidInt() method
for this!
*/
inline
float
hgeString::AsFloat() const
{
return float(atof( this->Get()));
}
// ------------------------------------------------------------------------------
/* *
*/
inline
bool
hgeString::AsBool() const
{
static const char* bools[] = {
"no", "yes", "off", "on", "false", "true", 0
};
int i = 0;
while (bools[i] != 0)
{
if (0 == stricmp(bools[i], this->Get()))
{
return 1 == (i & 1);
}
i++;
}
return false;
}
// ------------------------------------------------------------------------------
/* *
*/
inline
void __cdecl
hgeString::Format( const char* fmtString, ...)
{
va_list argList;
va_start(argList, fmtString);
this->FormatWithArgs(fmtString, argList);
va_end(argList);
}
// ------------------------------------------------------------------------------
/* *
*/
inline
void
hgeString::FormatWithArgs( const char* fmtString, va_list args)
{
va_list argList;
// First calculate the required length
argList = args;
size_t requiredLength;
requiredLength = _vscprintf(fmtString, argList);
requiredLength++; // Account for NULL termination
va_end(argList);
// Now we can allocate a buffer of the right length
char* buf = ( char*)alloca(requiredLength);
// Now do the formatting
_vsnprintf(buf, requiredLength, fmtString, args);
this->Set(buf);
}
// ------------------------------------------------------------------------------
/* *
*/
inline
void
hgeString::SetLength(size_t length)
{
if ( this-> string != 0)
{
this->strLen = (unsigned int)length;
}
else
{
this->localStrLen = (unsigned short)length;
}
}
// ------------------------------------------------------------------------------
/* *
*/
inline
void
hgeString::ReplaceIllegalFilenameChars( char replacement)
{
this->ReplaceChars("//:*?"<>|", replacement);
}
// ------------------------------------------------------------------------------
/* *
*/
inline
hgeString
hgeString::FromInt( int i)
{
hgeString str;
str.SetInt(i);
return str;
}
// ------------------------------------------------------------------------------
/* *
*/
inline
hgeString
hgeString::FromFloat( float f)
{
hgeString str;
str.SetFloat(f);
return str;
}
// ------------------------------------------------------------------------------
/* *
*/
inline
hgeString
hgeString::FromBool( bool b)
{
hgeString str;
str.SetBool(b);
return str;
}
// 修改来自于nebula2引擎,代码原作属于nebula2.
代码有点长.