93 lines
2.5 KiB
Plaintext
93 lines
2.5 KiB
Plaintext
|
//========= Copyright c 1996-2014, Valve Corporation, All rights reserved. ============//
|
||
|
//
|
||
|
// Purpose:
|
||
|
//
|
||
|
//=============================================================================//
|
||
|
|
||
|
static inline void CopyStringTruncatingMalformedUTF8Tail( char *pchBuffer, char const *szSrc, int numBufferBytes )
|
||
|
{
|
||
|
//
|
||
|
// There's a bug in Steam client where the clan tag may be truncated
|
||
|
// in the middle of UTF-8 sequence. Also we have a more restrictive
|
||
|
// clan tags length in the game to not bloat the name string.
|
||
|
//
|
||
|
|
||
|
if ( numBufferBytes <= 0 )
|
||
|
{
|
||
|
Assert( numBufferBytes > 0 );
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if ( numBufferBytes == 1 )
|
||
|
{
|
||
|
pchBuffer[0] = 0;
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
int nStrLen = V_strlen( szSrc );
|
||
|
if ( nStrLen <= 0 )
|
||
|
{
|
||
|
pchBuffer[ 0 ] = 0;
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
// Now we know that input is non-empty string, and buffer can hold at least one character
|
||
|
// let's figure out how many characters can fit?
|
||
|
|
||
|
if ( nStrLen > numBufferBytes - 1 )
|
||
|
nStrLen = numBufferBytes - 1;
|
||
|
|
||
|
//
|
||
|
// Check what the last character in the source string is?
|
||
|
//
|
||
|
// The last character is a UTF-8 sequence begin character or sequence continuation character
|
||
|
// See how many characters must have been in the end of the string?
|
||
|
for ( int numCheck = 0; numCheck < nStrLen; ++ numCheck )
|
||
|
{
|
||
|
int idxCheck = nStrLen - 1 - numCheck;
|
||
|
if ( ( szSrc[ idxCheck ] & ( 0x80 | 0x40 ) ) == ( 0x80 | 0x40 ) )
|
||
|
{
|
||
|
// This is the start of UTF8 sequence
|
||
|
int numCharactersSequenceLengthSeen = numCheck + 1;
|
||
|
int numCharactersSequenceMarker = 2; // at least two bytes
|
||
|
for ( uint8 uiMarker = uint8( uint8( szSrc[ idxCheck ] ) << 2 );
|
||
|
( ( uiMarker & 0x80 ) != 0 );
|
||
|
uiMarker <<= 1 )
|
||
|
++ numCharactersSequenceMarker;
|
||
|
|
||
|
// If the marker shows more characters than seen, discard the tail
|
||
|
if ( numCharactersSequenceMarker != numCharactersSequenceLengthSeen )
|
||
|
nStrLen -= numCharactersSequenceLengthSeen;
|
||
|
break;
|
||
|
}
|
||
|
else if ( ( szSrc[ idxCheck ] & ( 0x80 | 0x40 ) ) == ( 0x80 ) )
|
||
|
{
|
||
|
// This is a continuation of UTF8 sequence
|
||
|
if ( idxCheck )
|
||
|
continue; // Keep looking backwards
|
||
|
else
|
||
|
{ // Scanned all the way back to start of string and found no UTF8 sequence start character
|
||
|
nStrLen = 0;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// Looking at regular lower ASCII 0x00-0x7F character, valid for string termination
|
||
|
nStrLen -= numCheck;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if ( !nStrLen )
|
||
|
{
|
||
|
// This was an entirely invalid string, copy a questionmark
|
||
|
pchBuffer[0] = '?';
|
||
|
pchBuffer[1] = 0;
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
// Copy whatever we determined
|
||
|
V_strncpy( pchBuffer, szSrc, nStrLen + 1 );
|
||
|
}
|