Counter Strike : Global Offensive Source Code
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

92 lines
2.5 KiB

  1. //========= Copyright c 1996-2014, Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. //=============================================================================//
  6. static inline void CopyStringTruncatingMalformedUTF8Tail( char *pchBuffer, char const *szSrc, int numBufferBytes )
  7. {
  8. //
  9. // There's a bug in Steam client where the clan tag may be truncated
  10. // in the middle of UTF-8 sequence. Also we have a more restrictive
  11. // clan tags length in the game to not bloat the name string.
  12. //
  13. if ( numBufferBytes <= 0 )
  14. {
  15. Assert( numBufferBytes > 0 );
  16. return;
  17. }
  18. if ( numBufferBytes == 1 )
  19. {
  20. pchBuffer[0] = 0;
  21. return;
  22. }
  23. int nStrLen = V_strlen( szSrc );
  24. if ( nStrLen <= 0 )
  25. {
  26. pchBuffer[ 0 ] = 0;
  27. return;
  28. }
  29. // Now we know that input is non-empty string, and buffer can hold at least one character
  30. // let's figure out how many characters can fit?
  31. if ( nStrLen > numBufferBytes - 1 )
  32. nStrLen = numBufferBytes - 1;
  33. //
  34. // Check what the last character in the source string is?
  35. //
  36. // The last character is a UTF-8 sequence begin character or sequence continuation character
  37. // See how many characters must have been in the end of the string?
  38. for ( int numCheck = 0; numCheck < nStrLen; ++ numCheck )
  39. {
  40. int idxCheck = nStrLen - 1 - numCheck;
  41. if ( ( szSrc[ idxCheck ] & ( 0x80 | 0x40 ) ) == ( 0x80 | 0x40 ) )
  42. {
  43. // This is the start of UTF8 sequence
  44. int numCharactersSequenceLengthSeen = numCheck + 1;
  45. int numCharactersSequenceMarker = 2; // at least two bytes
  46. for ( uint8 uiMarker = uint8( uint8( szSrc[ idxCheck ] ) << 2 );
  47. ( ( uiMarker & 0x80 ) != 0 );
  48. uiMarker <<= 1 )
  49. ++ numCharactersSequenceMarker;
  50. // If the marker shows more characters than seen, discard the tail
  51. if ( numCharactersSequenceMarker != numCharactersSequenceLengthSeen )
  52. nStrLen -= numCharactersSequenceLengthSeen;
  53. break;
  54. }
  55. else if ( ( szSrc[ idxCheck ] & ( 0x80 | 0x40 ) ) == ( 0x80 ) )
  56. {
  57. // This is a continuation of UTF8 sequence
  58. if ( idxCheck )
  59. continue; // Keep looking backwards
  60. else
  61. { // Scanned all the way back to start of string and found no UTF8 sequence start character
  62. nStrLen = 0;
  63. break;
  64. }
  65. }
  66. else
  67. {
  68. // Looking at regular lower ASCII 0x00-0x7F character, valid for string termination
  69. nStrLen -= numCheck;
  70. break;
  71. }
  72. }
  73. if ( !nStrLen )
  74. {
  75. // This was an entirely invalid string, copy a questionmark
  76. pchBuffer[0] = '?';
  77. pchBuffer[1] = 0;
  78. return;
  79. }
  80. // Copy whatever we determined
  81. V_strncpy( pchBuffer, szSrc, nStrLen + 1 );
  82. }