// 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;
}