@ -16,6 +16,22 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program . If not , see < http : //www.gnu.org/licenses/>.
Additional permissions under GNU GPL version 3 section 7
If you modify this Program , or any covered work , by linking or
combining it with any of RAD Game Tools Bink SDK , Autodesk 3 ds Max SDK ,
NVIDIA PhysX SDK , Microsoft DirectX SDK , OpenSSL library , Independent
JPEG Group JPEG library , Microsoft Windows Media SDK , or Apple QuickTime SDK
( or a modified version of those libraries ) ,
containing parts covered by the terms of the Bink SDK EULA , 3 ds Max EULA ,
PhysX SDK EULA , DirectX SDK EULA , OpenSSL and SSLeay licenses , IJG
JPEG Library README , Windows Media SDK EULA , or QuickTime SDK EULA , the
licensors of this Program grant you additional
permission to convey the resulting work . Corresponding Source for a
non - source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work .
You can contact Cyan Worlds , Inc . by email legal @ cyan . com
or by snail mail at :
Cyan Worlds , Inc .
@ -29,6 +45,7 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com
# include <cstring>
# include <cstdlib>
# include <wchar.h>
# include <memory>
const plString plString : : Null ;
@ -67,7 +84,7 @@ size_t wcsnlen(const wchar_t *s, size_t maxlen)
# define BADCHAR_REPLACEMENT (0xFFFDul)
void plString : : IConvertFromUtf8 ( const char * utf8 , size_t size , bool steal )
void plString : : IConvertFromUtf8 ( const char * utf8 , size_t size )
{
if ( utf8 = = nil ) {
fUtf8Buffer = plStringBuffer < char > ( ) ;
@ -77,10 +94,17 @@ void plString::IConvertFromUtf8(const char *utf8, size_t size, bool steal)
if ( ( int32_t ) size < 0 )
size = strnlen ( utf8 , - ( int32_t ) size ) ;
operator = ( plStringBuffer < char > ( utf8 , size ) ) ;
}
plString & plString : : operator = ( const plStringBuffer < char > & init )
{
fUtf8Buffer = init ;
# ifdef _DEBUG
// Check to make sure the string is actually valid UTF-8
const char * sp = utf8 ;
while ( sp < utf8 + size ) {
const char * sp = fUtf8Buffer . GetData ( ) ;
while ( sp < fUtf8Buffer . GetData ( ) + fUtf8Buffer . GetSize ( ) ) {
unsigned char unichar = * sp + + ;
if ( ( unichar & 0xF8 ) = = 0xF0 ) {
// Four bytes
@ -102,16 +126,14 @@ void plString::IConvertFromUtf8(const char *utf8, size_t size, bool steal)
}
# endif
fUtf8Buffer = steal ? plStringBuffer < char > : : Steal ( utf8 , size )
: plStringBuffer < char > ( utf8 , size ) ;
return * this ;
}
void plString : : IConvertFromUtf16 ( const uint16_t * utf16 , size_t size )
{
if ( utf16 = = nil ) {
fUtf8Buffer = plStringBuffer < char > ( ) ;
fUtf8Buffer = plStringBuffer < char > ( ) ;
if ( utf16 = = nil )
return ;
}
if ( ( int32_t ) size < 0 )
size = u16slen ( utf16 , - ( int32_t ) size ) ;
@ -135,7 +157,7 @@ void plString::IConvertFromUtf16(const uint16_t *utf16, size_t size)
}
// And perform the actual conversion
char * utf8 = new char [ convlen + 1 ] ;
char * utf8 = fUtf8Buffer . CreateWritableBuffer ( convlen ) ;
char * dp = utf8 ;
sp = utf16 ;
while ( sp < utf16 + size ) {
@ -174,8 +196,6 @@ void plString::IConvertFromUtf16(const uint16_t *utf16, size_t size)
+ + sp ;
}
utf8 [ convlen ] = 0 ;
fUtf8Buffer = plStringBuffer < char > : : Steal ( utf8 , convlen ) ;
}
void plString : : IConvertFromWchar ( const wchar_t * wstr , size_t size )
@ -184,10 +204,9 @@ void plString::IConvertFromWchar(const wchar_t *wstr, size_t size)
// We assume that if sizeof(wchar_t) == 2, the data is UTF-16 already
IConvertFromUtf16 ( ( const uint16_t * ) wstr , size ) ;
# else
if ( wstr = = nil ) {
fUtf8Buffer = plStringBuffer < char > ( ) ;
fUtf8Buffer = plStringBuffer < char > ( ) ;
if ( wstr = = nil )
return ;
}
if ( ( int32_t ) size < 0 )
size = wcsnlen ( wstr , - ( int32_t ) size ) ;
@ -212,7 +231,7 @@ void plString::IConvertFromWchar(const wchar_t *wstr, size_t size)
}
// And perform the actual conversion
char * utf8 = new char [ convlen + 1 ] ;
char * utf8 = fUtf8Buffer . CreateWritableBuffer ( convlen ) ;
char * dp = utf8 ;
sp = wstr ;
while ( sp < wstr + size ) {
@ -239,17 +258,14 @@ void plString::IConvertFromWchar(const wchar_t *wstr, size_t size)
+ + sp ;
}
utf8 [ convlen ] = 0 ;
fUtf8Buffer = plStringBuffer < char > : : Steal ( utf8 , convlen ) ;
# endif
}
void plString : : IConvertFromIso8859_1 ( const char * astr , size_t size )
{
if ( astr = = nil ) {
fUtf8Buffer = plStringBuffer < char > ( ) ;
fUtf8Buffer = plStringBuffer < char > ( ) ;
if ( astr = = nil )
return ;
}
if ( ( int32_t ) size < 0 )
size = strnlen ( astr , - ( int32_t ) size ) ;
@ -265,7 +281,7 @@ void plString::IConvertFromIso8859_1(const char *astr, size_t size)
}
// And perform the actual conversion
char * utf8 = new char [ convlen + 1 ] ;
char * utf8 = fUtf8Buffer . CreateWritableBuffer ( convlen ) ;
char * dp = utf8 ;
sp = astr ;
while ( sp < astr + size ) {
@ -278,14 +294,13 @@ void plString::IConvertFromIso8859_1(const char *astr, size_t size)
+ + sp ;
}
utf8 [ convlen ] = 0 ;
fUtf8Buffer = plStringBuffer < char > : : Steal ( utf8 , convlen ) ;
}
plStringBuffer < uint16_t > plString : : ToUtf16 ( ) const
{
if ( IsNull ( ) )
return plStringBuffer < uint16_t > ( ) ;
plStringBuffer < uint16_t > result ;
if ( IsEmpty ( ) )
return result ;
// Calculate the UTF-16 size
size_t convlen = 0 ;
@ -308,7 +323,7 @@ plStringBuffer<uint16_t> plString::ToUtf16() const
}
// And perform the actual conversion
uint16_t * ustr = new uint16_t [ convlen + 1 ] ;
uint16_t * ustr = result . CreateWritableBuffer ( convlen ) ;
uint16_t * dp = ustr ;
sp = utf8 ;
while ( sp < utf8 + srcSize ) {
@ -336,7 +351,7 @@ plStringBuffer<uint16_t> plString::ToUtf16() const
}
ustr [ convlen ] = 0 ;
return plSt ringBuff er < uint16_t > : : Steal ( ustr , convlen ) ;
return res ult ;
}
plStringBuffer < wchar_t > plString : : ToWchar ( ) const
@ -346,8 +361,9 @@ plStringBuffer<wchar_t> plString::ToWchar() const
plStringBuffer < uint16_t > utf16 = ToUtf16 ( ) ;
return * reinterpret_cast < plStringBuffer < wchar_t > * > ( & utf16 ) ;
# else
if ( IsNull ( ) )
return plStringBuffer < wchar_t > ( ) ;
plStringBuffer < uint16_t > result ;
if ( IsEmpty ( ) )
return result ;
// Calculate the UCS-4 size
size_t convlen = 0 ;
@ -367,7 +383,7 @@ plStringBuffer<wchar_t> plString::ToWchar() const
}
// And perform the actual conversion
wchar_t * wstr = new wchar_t [ convlen + 1 ] ;
wchar_t * wstr = result . CreateWritableBuffer ( convlen ) ;
wchar_t * dp = wstr ;
sp = utf8 ;
while ( sp < utf8 + srcSize ) {
@ -391,14 +407,15 @@ plStringBuffer<wchar_t> plString::ToWchar() const
}
wstr [ convlen ] = 0 ;
return plStringBuffer < wchar_t > : : Steal ( wstr , convlen ) ;
return result ;
# endif
}
plStringBuffer < char > plString : : ToIso8859_1 ( ) const
{
if ( IsNull ( ) )
return plStringBuffer < char > ( ) ;
plStringBuffer < char > result ;
if ( IsEmpty ( ) )
return result ;
// Calculate the ASCII size
size_t convlen = 0 ;
@ -418,7 +435,7 @@ plStringBuffer<char> plString::ToIso8859_1() const
}
// And perform the actual conversion
char * astr = new char [ convlen + 1 ] ;
char * astr = result . CreateWritableBuffer ( convlen ) ;
char * dp = astr ;
sp = utf8 ;
while ( sp < utf8 + srcSize ) {
@ -442,45 +459,45 @@ plStringBuffer<char> plString::ToIso8859_1() const
}
astr [ convlen ] = 0 ;
return plStringBuffer < char > : : Steal ( astr , convlen ) ;
return result ;
}
plStringBuffer < UniChar > plString : : GetUnicodeArray ( ) const
{
static UniChar empty [ 1 ] = { 0 } ;
if ( IsNull ( ) )
return plStringBuffer < UniChar > ( empty , 0 ) ;
plStringBuffer < UniChar > result ;
if ( IsEmpty ( ) )
return result ;
size_t convlen = GetUniCharCount ( ) ;
UniChar * ustr = new UniChar [ convlen + 1 ] ;
UniChar * ustr = result . CreateWritableBuffer ( convlen ) ;
iterator iter = GetIterator ( ) ;
size_t dp = 0 ;
while ( ! iter . AtEnd ( ) )
ustr [ dp + + ] = * iter + + ;
ustr [ convlen ] = 0 ;
return plStringBuffer < UniChar > : : Steal ( ustr , convlen ) ;
return result ;
}
int plString : : ToInt ( int base ) const
{
return static_cast < int > ( strtol ( s _str( ) , nil , base ) ) ;
return static_cast < int > ( strtol ( c _str( ) , nil , base ) ) ;
}
unsigned int plString : : ToUInt ( int base ) const
{
return static_cast < unsigned int > ( strtoul ( s _str( ) , nil , base ) ) ;
return static_cast < unsigned int > ( strtoul ( c _str( ) , nil , base ) ) ;
}
float plString : : ToFloat ( ) const
{
// strtof is C99, which MS doesn't support...
return ( float ) strtod ( s _str( ) , nil ) ;
return ( float ) strtod ( c _str( ) , nil ) ;
}
double plString : : ToDouble ( ) const
{
return strtod ( s _str( ) , nil ) ;
return strtod ( c _str( ) , nil ) ;
}
// Microsoft doesn't provide this for us
@ -501,22 +518,21 @@ plString plString::IFormat(const char *fmt, va_list vptr)
int size = 4096 ;
for ( ; ; ) {
va_copy ( vptr , vptr_save ) ;
char * bigbuffer = new char [ size ] ;
chars = vsnprintf ( bigbuffer , size , fmt , vptr ) ;
std : : auto_ptr < char > bigbuffer ( new char [ size ] ) ;
chars = vsnprintf ( bigbuffer . get ( ) , size , fmt , vptr ) ;
if ( chars > = 0 )
return plString : : Steal ( bigbuffer ) ;
return plString : : FromUtf8 ( bigbuffer . get ( ) , chars ) ;
delete [ ] bigbuffer ;
size * = 2 ;
}
} else if ( chars > = 256 ) {
va_copy ( vptr , vptr_save ) ;
char * bigbuffer = new char [ chars + 1 ] ;
vsnprintf ( bigbuffer , chars + 1 , fmt , vptr ) ;
return plString : : Steal ( bigbuffer ) ;
std : : auto_ptr < char > bigbuffer ( new char [ chars + 1 ] ) ;
vsnprintf ( bigbuffer . get ( ) , chars + 1 , fmt , vptr ) ;
return plString : : FromUtf8 ( bigbuffer . get ( ) , chars ) ;
}
return plString : : FromUtf8 ( buffer ) ;
return plString : : FromUtf8 ( buffer , chars ) ;
}
plString plString : : Format ( const char * fmt , . . . )
@ -531,11 +547,10 @@ plString plString::Format(const char *fmt, ...)
int plString : : Find ( char ch , CaseSensitivity sense ) const
{
if ( sense = = kCaseSensitive ) {
const char * cp = strchr ( s _str( ) , ch ) ;
const char * cp = strchr ( c _str( ) , ch ) ;
return cp ? ( cp - c_str ( ) ) : - 1 ;
} else {
// No need to check for null, since s_str() will return { 0 } if it is null
const char * cp = s_str ( ) ;
const char * cp = c_str ( ) ;
while ( * cp ) {
if ( tolower ( * cp ) = = tolower ( ch ) )
return cp - c_str ( ) ;
@ -550,7 +565,7 @@ int plString::FindLast(char ch, CaseSensitivity sense) const
return - 1 ;
if ( sense = = kCaseSensitive ) {
const char * cp = strrchr ( s _str( ) , ch ) ;
const char * cp = strrchr ( c _str( ) , ch ) ;
return cp ? ( cp - c_str ( ) ) : - 1 ;
} else {
const char * cp = c_str ( ) ;
@ -570,7 +585,7 @@ int plString::Find(const char *str, CaseSensitivity sense) const
return - 1 ;
if ( sense = = kCaseSensitive ) {
const char * cp = strstr ( s _str( ) , str ) ;
const char * cp = strstr ( c _str( ) , str ) ;
return cp ? ( cp - c_str ( ) ) : - 1 ;
} else {
// The easy way
@ -651,69 +666,49 @@ plString plString::Substr(int start, size_t size) const
if ( start = = 0 & & size = = maxSize )
return * this ;
char * substr = new char [ size + 1 ] ;
plString sub ;
char * substr = sub . fUtf8Buffer . CreateWritableBuffer ( size ) ;
memcpy ( substr , c_str ( ) + start , size ) ;
substr [ size ] = 0 ;
// Don't re-check UTF-8 on this
plString str ;
str . fUtf8Buffer = plStringBuffer < char > : : Steal ( substr , size ) ;
return str ;
return sub ;
}
plString plString : : ToUpper ( ) const
{
// TODO: Unicode-aware case conversion
size_t size = GetSize ( ) ;
char * dupe = new char [ size + 1 ] ;
plString str ;
char * dupe = str . fUtf8Buffer . CreateWritableBuffer ( fUtf8Buffer . GetSize ( ) ) ;
const char * self = c_str ( ) ;
for ( size_t i = 0 ; i < s ize; + + i )
for ( size_t i = 0 ; i < fUtf8Buffer . GetS ize( ) ; + + i )
dupe [ i ] = toupper ( self [ i ] ) ;
dupe [ fUtf8Buffer . GetSize ( ) ] = 0 ;
// Don't re-check UTF-8 on this
plString str ;
str . fUtf8Buffer = plStringBuffer < char > : : Steal ( dupe , size ) ;
return str ;
}
plString plString : : ToLower ( ) const
{
// TODO: Unicode-aware case conversion
size_t size = GetSize ( ) ;
char * dupe = new char [ size + 1 ] ;
plString str ;
char * dupe = str . fUtf8Buffer . CreateWritableBuffer ( fUtf8Buffer . GetSize ( ) ) ;
const char * self = c_str ( ) ;
for ( size_t i = 0 ; i < s ize; + + i )
for ( size_t i = 0 ; i < fUtf8Buffer . GetS ize( ) ; + + i )
dupe [ i ] = tolower ( self [ i ] ) ;
dupe [ fUtf8Buffer . GetSize ( ) ] = 0 ;
// Don't re-check UTF-8 on this
plString str ;
str . fUtf8Buffer = plStringBuffer < char > : : Steal ( dupe , size ) ;
return str ;
}
plString & plString : : operator + = ( const plString & str )
{
size_t catsize = GetSize ( ) + str . GetSize ( ) ;
char * catstr = new char [ catsize + 1 ] ;
memcpy ( catstr , s_str ( ) , GetSize ( ) ) ;
memcpy ( catstr + GetSize ( ) , str . s_str ( ) , str . GetSize ( ) ) ;
catstr [ catsize ] = 0 ;
fUtf8Buffer = plStringBuffer < char > : : Steal ( catstr , catsize ) ;
return * this ;
}
plString operator + ( const plString & left , const plString & right )
{
size_t catsize = left . GetSize ( ) + right . GetSize ( ) ;
char * catstr = new char [ catsize + 1 ] ;
memcpy ( catstr , left . s _str( ) , left . GetSize ( ) ) ;
memcpy ( catstr + left . GetSize ( ) , right . s _str( ) , right . GetSize ( ) ) ;
catstr [ cats ize ] = 0 ;
plString cat ;
char * catstr = cat . fUtf8Buffer . CreateWritableBuffer ( left . GetSize ( ) + right . GetSize ( ) ) ;
memcpy ( catstr , left . c_str ( ) , left . GetSize ( ) ) ;
memcpy ( catstr + left . GetSize ( ) , right . c_str ( ) , right . GetSize ( ) ) ;
catstr [ cat . fUtf8Buffer . GetSize ( ) ] = 0 ;
// Don't re-check UTF-8 on this
plString str ;
str . fUtf8Buffer = plStringBuffer < char > : : Steal ( catstr , catsize ) ;
return str ;
return cat ;
}
plStringStream & plStringStream : : append ( const char * data , size_t length )