让HGE支持中文(3) - HGE字符串处理

本文介绍了一个在HGE(HGE Game Engine)中使用的CString类的实现细节,该类主要用于处理字符串操作,如查找、替换、格式化等,并提供了完整的源代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前面都已经讲了怎么请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

// 修改来自于nebula2引擎,代码原作属于nebula2.

代码有点长.

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值