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.

561 lines
21 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //
  7. //=============================================================================//
  8. #include "tier0/dbg.h"
  9. #include "tier1/strtools.h"
  10. //-----------------------------------------------------------------------------
  11. // Purpose: determine if a uchar32 represents a valid Unicode code point
  12. //-----------------------------------------------------------------------------
  13. bool Q_IsValidUChar32( uchar32 uVal )
  14. {
  15. // Values > 0x10FFFF are explicitly invalid; ditto for UTF-16 surrogate halves,
  16. // values ending in FFFE or FFFF, or values in the 0x00FDD0-0x00FDEF reserved range
  17. return ( uVal < 0x110000u ) && ( (uVal - 0x00D800u) > 0x7FFu ) && ( (uVal & 0xFFFFu) < 0xFFFEu ) && ( ( uVal - 0x00FDD0u ) > 0x1Fu );
  18. }
  19. //-----------------------------------------------------------------------------
  20. // Purpose: return number of UTF-8 bytes required to encode a Unicode code point
  21. //-----------------------------------------------------------------------------
  22. int Q_UChar32ToUTF8Len( uchar32 uVal )
  23. {
  24. DbgAssert( Q_IsValidUChar32( uVal ) );
  25. if ( uVal <= 0x7F )
  26. return 1;
  27. if ( uVal <= 0x7FF )
  28. return 2;
  29. if ( uVal <= 0xFFFF )
  30. return 3;
  31. return 4;
  32. }
  33. //-----------------------------------------------------------------------------
  34. // Purpose: return number of UTF-16 elements required to encode a Unicode code point
  35. //-----------------------------------------------------------------------------
  36. int Q_UChar32ToUTF16Len( uchar32 uVal )
  37. {
  38. DbgAssert( Q_IsValidUChar32( uVal ) );
  39. if ( uVal <= 0xFFFF )
  40. return 1;
  41. return 2;
  42. }
  43. //-----------------------------------------------------------------------------
  44. // Purpose: encode Unicode code point as UTF-8, returns number of bytes written
  45. //-----------------------------------------------------------------------------
  46. int Q_UChar32ToUTF8( uchar32 uVal, char *pUTF8Out )
  47. {
  48. DbgAssert( Q_IsValidUChar32( uVal ) );
  49. if ( uVal <= 0x7F )
  50. {
  51. pUTF8Out[0] = (unsigned char) uVal;
  52. return 1;
  53. }
  54. if ( uVal <= 0x7FF )
  55. {
  56. pUTF8Out[0] = (unsigned char)(uVal >> 6) | 0xC0;
  57. pUTF8Out[1] = (unsigned char)(uVal & 0x3F) | 0x80;
  58. return 2;
  59. }
  60. if ( uVal <= 0xFFFF )
  61. {
  62. pUTF8Out[0] = (unsigned char)(uVal >> 12) | 0xE0;
  63. pUTF8Out[1] = (unsigned char)((uVal >> 6) & 0x3F) | 0x80;
  64. pUTF8Out[2] = (unsigned char)(uVal & 0x3F) | 0x80;
  65. return 3;
  66. }
  67. pUTF8Out[0] = (unsigned char)((uVal >> 18) & 0x07) | 0xF0;
  68. pUTF8Out[1] = (unsigned char)((uVal >> 12) & 0x3F) | 0x80;
  69. pUTF8Out[2] = (unsigned char)((uVal >> 6) & 0x3F) | 0x80;
  70. pUTF8Out[3] = (unsigned char)(uVal & 0x3F) | 0x80;
  71. return 4;
  72. }
  73. //-----------------------------------------------------------------------------
  74. // Purpose: encode Unicode code point as UTF-16, returns number of elements written
  75. //-----------------------------------------------------------------------------
  76. int Q_UChar32ToUTF16( uchar32 uVal, uchar16 *pUTF16Out )
  77. {
  78. DbgAssert( Q_IsValidUChar32( uVal ) );
  79. if ( uVal <= 0xFFFF )
  80. {
  81. pUTF16Out[0] = (uchar16) uVal;
  82. return 1;
  83. }
  84. uVal -= 0x010000;
  85. pUTF16Out[0] = (uchar16)(uVal >> 10) | 0xD800;
  86. pUTF16Out[1] = (uchar16)(uVal & 0x3FF) | 0xDC00;
  87. return 2;
  88. }
  89. // Decode one character from a UTF-8 encoded string. Treats 6-byte CESU-8 sequences
  90. // as a single character, as if they were a correctly-encoded 4-byte UTF-8 sequence.
  91. int Q_UTF8ToUChar32( const char *pUTF8_, uchar32 &uValueOut, bool &bErrorOut )
  92. {
  93. const uint8 *pUTF8 = (const uint8 *)pUTF8_;
  94. int nBytes = 1;
  95. uint32 uValue = pUTF8[0];
  96. uint32 uMinValue = 0;
  97. // 0....... single byte
  98. if ( uValue < 0x80 )
  99. goto decodeFinishedNoCheck;
  100. // Expecting at least a two-byte sequence with 0xC0 <= first <= 0xF7 (110...... and 11110...)
  101. if ( (uValue - 0xC0u) > 0x37u || ( pUTF8[1] & 0xC0 ) != 0x80 )
  102. goto decodeError;
  103. uValue = (uValue << 6) - (0xC0 << 6) + pUTF8[1] - 0x80;
  104. nBytes = 2;
  105. uMinValue = 0x80;
  106. // 110..... two-byte lead byte
  107. if ( !( uValue & (0x20 << 6) ) )
  108. goto decodeFinished;
  109. // Expecting at least a three-byte sequence
  110. if ( ( pUTF8[2] & 0xC0 ) != 0x80 )
  111. goto decodeError;
  112. uValue = (uValue << 6) - (0x20 << 12) + pUTF8[2] - 0x80;
  113. nBytes = 3;
  114. uMinValue = 0x800;
  115. // 1110.... three-byte lead byte
  116. if ( !( uValue & (0x10 << 12) ) )
  117. goto decodeFinishedMaybeCESU8;
  118. // Expecting a four-byte sequence, longest permissible in UTF-8
  119. if ( ( pUTF8[3] & 0xC0 ) != 0x80 )
  120. goto decodeError;
  121. uValue = (uValue << 6) - (0x10 << 18) + pUTF8[3] - 0x80;
  122. nBytes = 4;
  123. uMinValue = 0x10000;
  124. // 11110... four-byte lead byte. fall through to finished.
  125. decodeFinished:
  126. if ( uValue >= uMinValue && Q_IsValidUChar32( uValue ) )
  127. {
  128. decodeFinishedNoCheck:
  129. uValueOut = uValue;
  130. bErrorOut = false;
  131. return nBytes;
  132. }
  133. decodeError:
  134. uValueOut = '?';
  135. bErrorOut = true;
  136. return nBytes;
  137. decodeFinishedMaybeCESU8:
  138. // Do we have a full UTF-16 surrogate pair that's been UTF-8 encoded afterwards?
  139. // That is, do we have 0xD800-0xDBFF followed by 0xDC00-0xDFFF? If so, decode it all.
  140. if ( ( uValue - 0xD800u ) < 0x400u && pUTF8[3] == 0xED && (uint8)( pUTF8[4] - 0xB0 ) < 0x10 && ( pUTF8[5] & 0xC0 ) == 0x80 )
  141. {
  142. uValue = 0x10000 + ( ( uValue - 0xD800u ) << 10 ) + ( (uint8)( pUTF8[4] - 0xB0 ) << 6 ) + pUTF8[5] - 0x80;
  143. nBytes = 6;
  144. uMinValue = 0x10000;
  145. }
  146. goto decodeFinished;
  147. }
  148. // Decode one character from a UTF-16 encoded string.
  149. int Q_UTF16ToUChar32( const uchar16 *pUTF16, uchar32 &uValueOut, bool &bErrorOut )
  150. {
  151. if ( Q_IsValidUChar32( pUTF16[0] ) )
  152. {
  153. uValueOut = pUTF16[0];
  154. bErrorOut = false;
  155. return 1;
  156. }
  157. else if ( (pUTF16[0] - 0xD800u) < 0x400u && (pUTF16[1] - 0xDC00u) < 0x400u )
  158. {
  159. // Valid surrogate pair, but maybe not encoding a valid Unicode code point...
  160. uchar32 uVal = 0x010000 + ((pUTF16[0] - 0xD800u) << 10) + (pUTF16[1] - 0xDC00);
  161. if ( Q_IsValidUChar32( uVal ) )
  162. {
  163. uValueOut = uVal;
  164. bErrorOut = false;
  165. return 2;
  166. }
  167. else
  168. {
  169. uValueOut = '?';
  170. bErrorOut = true;
  171. return 2;
  172. }
  173. }
  174. else
  175. {
  176. uValueOut = '?';
  177. bErrorOut = true;
  178. return 1;
  179. }
  180. }
  181. namespace // internal use only
  182. {
  183. // Identity transformations and validity tests for use with Q_UnicodeConvertT
  184. int Q_UTF32ToUChar32( const uchar32 *pUTF32, uchar32 &uVal, bool &bErr )
  185. {
  186. bErr = !Q_IsValidUChar32( *pUTF32 );
  187. uVal = bErr ? '?' : *pUTF32;
  188. return 1;
  189. }
  190. int Q_UChar32ToUTF32Len( uchar32 uVal )
  191. {
  192. return 1;
  193. }
  194. int Q_UChar32ToUTF32( uchar32 uVal, uchar32 *pUTF32 )
  195. {
  196. *pUTF32 = uVal;
  197. return 1;
  198. }
  199. // A generic Unicode processing loop: decode one character from input to uchar32, handle errors, encode uchar32 to output
  200. template < typename SrcType, typename DstType, bool bStopAtNull, int (&DecodeSrc)( const SrcType*, uchar32&, bool& ), int (&EncodeDstLen)( uchar32 ), int (&EncodeDst)( uchar32, DstType* ) >
  201. int Q_UnicodeConvertT( const SrcType *pIn, int nInChars, DstType *pOut, int nOutBytes, EStringConvertErrorPolicy ePolicy )
  202. {
  203. int nOut = 0;
  204. if ( !pOut )
  205. {
  206. while ( bStopAtNull ? ( *pIn ) : ( nInChars-- > 0 ) )
  207. {
  208. uchar32 uVal;
  209. // Initialize in order to avoid /analyze warnings.
  210. bool bErr = false;
  211. pIn += DecodeSrc( pIn, uVal, bErr );
  212. nOut += EncodeDstLen( uVal );
  213. if ( bErr )
  214. {
  215. #ifdef _DEBUG
  216. AssertMsg( !(ePolicy & _STRINGCONVERTFLAG_ASSERT), "invalid Unicode byte sequence" );
  217. #endif
  218. if ( ePolicy & _STRINGCONVERTFLAG_SKIP )
  219. {
  220. nOut -= EncodeDstLen( uVal );
  221. }
  222. else if ( ePolicy & _STRINGCONVERTFLAG_FAIL )
  223. {
  224. pOut[0] = 0;
  225. return 0;
  226. }
  227. }
  228. }
  229. }
  230. else
  231. {
  232. int nOutElems = nOutBytes / sizeof( DstType );
  233. if ( nOutElems <= 0 )
  234. return 0;
  235. int nMaxOut = nOutElems - 1;
  236. while ( bStopAtNull ? ( *pIn ) : ( nInChars-- > 0 ) )
  237. {
  238. uchar32 uVal;
  239. // Initialize in order to avoid /analyze warnings.
  240. bool bErr = false;
  241. pIn += DecodeSrc( pIn, uVal, bErr );
  242. if ( nOut + EncodeDstLen( uVal ) > nMaxOut )
  243. break;
  244. nOut += EncodeDst( uVal, pOut + nOut );
  245. if ( bErr )
  246. {
  247. #ifdef _DEBUG
  248. AssertMsg( !(ePolicy & _STRINGCONVERTFLAG_ASSERT), "invalid Unicode byte sequence" );
  249. #endif
  250. if ( ePolicy & _STRINGCONVERTFLAG_SKIP )
  251. {
  252. nOut -= EncodeDstLen( uVal );
  253. }
  254. else if ( ePolicy & _STRINGCONVERTFLAG_FAIL )
  255. {
  256. pOut[0] = 0;
  257. return 0;
  258. }
  259. }
  260. }
  261. pOut[nOut] = 0;
  262. }
  263. return (nOut + 1) * sizeof( DstType );
  264. }
  265. }
  266. //-----------------------------------------------------------------------------
  267. // Purpose: Returns true if UTF-8 string contains invalid sequences.
  268. //-----------------------------------------------------------------------------
  269. bool Q_UnicodeValidate( const char *pUTF8 )
  270. {
  271. bool bError = false;
  272. while ( *pUTF8 )
  273. {
  274. uchar32 uVal;
  275. // Our UTF-8 decoder silently fixes up 6-byte CESU-8 (improperly re-encoded UTF-16) sequences.
  276. // However, these are technically not valid UTF-8. So if we eat 6 bytes at once, it's an error.
  277. int nCharSize = Q_UTF8ToUChar32( pUTF8, uVal, bError );
  278. if ( bError || nCharSize == 6 )
  279. return false;
  280. pUTF8 += nCharSize;
  281. }
  282. return true;
  283. }
  284. //-----------------------------------------------------------------------------
  285. // Purpose: Returns true if UTF-16 string contains invalid sequences.
  286. //-----------------------------------------------------------------------------
  287. bool Q_UnicodeValidate( const uchar16 *pUTF16 )
  288. {
  289. bool bError = false;
  290. while ( *pUTF16 )
  291. {
  292. uchar32 uVal;
  293. pUTF16 += Q_UTF16ToUChar32( pUTF16, uVal, bError );
  294. if ( bError )
  295. return false;
  296. }
  297. return true;
  298. }
  299. //-----------------------------------------------------------------------------
  300. // Purpose: Returns true if UTF-32 string contains invalid sequences.
  301. //-----------------------------------------------------------------------------
  302. bool Q_UnicodeValidate( const uchar32 *pUTF32 )
  303. {
  304. while ( *pUTF32 )
  305. {
  306. if ( !Q_IsValidUChar32( *pUTF32++ ) )
  307. return false;
  308. ++pUTF32;
  309. }
  310. return true;
  311. }
  312. //-----------------------------------------------------------------------------
  313. // Purpose: Returns number of Unicode code points (aka glyphs / characters) encoded in the UTF-8 string
  314. //-----------------------------------------------------------------------------
  315. int Q_UnicodeLength( const char *pUTF8 )
  316. {
  317. int nChars = 0;
  318. while ( *pUTF8 )
  319. {
  320. bool bError;
  321. uchar32 uVal;
  322. pUTF8 += Q_UTF8ToUChar32( pUTF8, uVal, bError );
  323. ++nChars;
  324. }
  325. return nChars;
  326. }
  327. //-----------------------------------------------------------------------------
  328. // Purpose: Returns number of Unicode code points (aka glyphs / characters) encoded in the UTF-16 string
  329. //-----------------------------------------------------------------------------
  330. int Q_UnicodeLength( const uchar16 *pUTF16 )
  331. {
  332. int nChars = 0;
  333. while ( *pUTF16 )
  334. {
  335. bool bError;
  336. uchar32 uVal;
  337. pUTF16 += Q_UTF16ToUChar32( pUTF16, uVal, bError );
  338. ++nChars;
  339. }
  340. return nChars;
  341. }
  342. //-----------------------------------------------------------------------------
  343. // Purpose: Returns number of Unicode code points (aka glyphs / characters) encoded in the UTF-32 string
  344. //-----------------------------------------------------------------------------
  345. int Q_UnicodeLength( const uchar32 *pUTF32 )
  346. {
  347. int nChars = 0;
  348. while ( *pUTF32++ )
  349. ++nChars;
  350. return nChars;
  351. }
  352. //-----------------------------------------------------------------------------
  353. // Purpose: Advance a UTF-8 string pointer by a certain number of Unicode code points, stopping at end of string
  354. //-----------------------------------------------------------------------------
  355. char *Q_UnicodeAdvance( char *pUTF8, int nChars )
  356. {
  357. while ( nChars > 0 && *pUTF8 )
  358. {
  359. uchar32 uVal;
  360. bool bError;
  361. pUTF8 += Q_UTF8ToUChar32( pUTF8, uVal, bError );
  362. --nChars;
  363. }
  364. return pUTF8;
  365. }
  366. //-----------------------------------------------------------------------------
  367. // Purpose: Advance a UTF-16 string pointer by a certain number of Unicode code points, stopping at end of string
  368. //-----------------------------------------------------------------------------
  369. uchar16 *Q_UnicodeAdvance( uchar16 *pUTF16, int nChars )
  370. {
  371. while ( nChars > 0 && *pUTF16 )
  372. {
  373. uchar32 uVal;
  374. bool bError;
  375. pUTF16 += Q_UTF16ToUChar32( pUTF16, uVal, bError );
  376. --nChars;
  377. }
  378. return pUTF16;
  379. }
  380. //-----------------------------------------------------------------------------
  381. // Purpose: Advance a UTF-32 string pointer by a certain number of Unicode code points, stopping at end of string
  382. //-----------------------------------------------------------------------------
  383. uchar32 *Q_UnicodeAdvance( uchar32 *pUTF32, int nChars )
  384. {
  385. while ( nChars > 0 && *pUTF32 )
  386. {
  387. ++pUTF32;
  388. --nChars;
  389. }
  390. return pUTF32;
  391. }
  392. //-----------------------------------------------------------------------------
  393. // Purpose: Perform conversion. Returns number of *bytes* required if output pointer is NULL.
  394. //-----------------------------------------------------------------------------
  395. int Q_UTF8ToUTF16( const char *pUTF8, uchar16 *pUTF16, int cubDestSizeInBytes, EStringConvertErrorPolicy ePolicy )
  396. {
  397. return Q_UnicodeConvertT< char, uchar16, true, Q_UTF8ToUChar32, Q_UChar32ToUTF16Len, Q_UChar32ToUTF16 >( pUTF8, 0, pUTF16, cubDestSizeInBytes, ePolicy );
  398. }
  399. //-----------------------------------------------------------------------------
  400. // Purpose: Perform conversion. Returns number of *bytes* required if output pointer is NULL.
  401. //-----------------------------------------------------------------------------
  402. int Q_UTF8ToUTF32( const char *pUTF8, uchar32 *pUTF32, int cubDestSizeInBytes, EStringConvertErrorPolicy ePolicy )
  403. {
  404. return Q_UnicodeConvertT< char, uchar32, true, Q_UTF8ToUChar32, Q_UChar32ToUTF32Len, Q_UChar32ToUTF32 >( pUTF8, 0, pUTF32, cubDestSizeInBytes, ePolicy );
  405. }
  406. //-----------------------------------------------------------------------------
  407. // Purpose: Perform conversion. Returns number of *bytes* required if output pointer is NULL.
  408. //-----------------------------------------------------------------------------
  409. int Q_UTF16ToUTF8( const uchar16 *pUTF16, char *pUTF8, int cubDestSizeInBytes, EStringConvertErrorPolicy ePolicy )
  410. {
  411. return Q_UnicodeConvertT< uchar16, char, true, Q_UTF16ToUChar32, Q_UChar32ToUTF8Len, Q_UChar32ToUTF8 >( pUTF16, 0, pUTF8, cubDestSizeInBytes, ePolicy );
  412. }
  413. //-----------------------------------------------------------------------------
  414. // Purpose: Perform conversion. Returns number of *bytes* required if output pointer is NULL.
  415. //-----------------------------------------------------------------------------
  416. int Q_UTF16ToUTF32( const uchar16 *pUTF16, uchar32 *pUTF32, int cubDestSizeInBytes, EStringConvertErrorPolicy ePolicy )
  417. {
  418. return Q_UnicodeConvertT< uchar16, uchar32, true, Q_UTF16ToUChar32, Q_UChar32ToUTF32Len, Q_UChar32ToUTF32 >( pUTF16, 0, pUTF32, cubDestSizeInBytes, ePolicy );
  419. }
  420. //-----------------------------------------------------------------------------
  421. // Purpose: Perform conversion. Returns number of *bytes* required if output pointer is NULL.
  422. //-----------------------------------------------------------------------------
  423. int Q_UTF32ToUTF8( const uchar32 *pUTF32, char *pUTF8, int cubDestSizeInBytes, EStringConvertErrorPolicy ePolicy )
  424. {
  425. return Q_UnicodeConvertT< uchar32, char, true, Q_UTF32ToUChar32, Q_UChar32ToUTF8Len, Q_UChar32ToUTF8 >( pUTF32, 0, pUTF8, cubDestSizeInBytes, ePolicy );
  426. }
  427. //-----------------------------------------------------------------------------
  428. // Purpose: Perform conversion. Returns number of *bytes* required if output pointer is NULL.
  429. //-----------------------------------------------------------------------------
  430. int Q_UTF32ToUTF16( const uchar32 *pUTF32, uchar16 *pUTF16, int cubDestSizeInBytes, EStringConvertErrorPolicy ePolicy )
  431. {
  432. return Q_UnicodeConvertT< uchar32, uchar16, true, Q_UTF32ToUChar32, Q_UChar32ToUTF16Len, Q_UChar32ToUTF16 >( pUTF32, 0, pUTF16, cubDestSizeInBytes, ePolicy );
  433. }
  434. //-----------------------------------------------------------------------------
  435. // Purpose: Perform conversion. Returns number of *bytes* required if output pointer is NULL.
  436. //-----------------------------------------------------------------------------
  437. int Q_UTF32ToUTF32( const uchar32 *pUTF32Source, uchar32 *pUTF32Dest, int cubDestSizeInBytes, EStringConvertErrorPolicy ePolicy )
  438. {
  439. return Q_UnicodeConvertT< uchar32, uchar32, true, Q_UTF32ToUChar32, Q_UChar32ToUTF32Len, Q_UChar32ToUTF32 >( pUTF32Source, 0, pUTF32Dest, cubDestSizeInBytes, ePolicy );
  440. }
  441. //-----------------------------------------------------------------------------
  442. // Purpose: Perform conversion. Returns number of *bytes* required if output pointer is NULL.
  443. //-----------------------------------------------------------------------------
  444. int Q_UTF8CharsToUTF16( const char *pUTF8, int nElements, uchar16 *pUTF16, int cubDestSizeInBytes, EStringConvertErrorPolicy ePolicy )
  445. {
  446. return Q_UnicodeConvertT< char, uchar16, false, Q_UTF8ToUChar32, Q_UChar32ToUTF16Len, Q_UChar32ToUTF16 >( pUTF8, nElements, pUTF16, cubDestSizeInBytes, ePolicy );
  447. }
  448. //-----------------------------------------------------------------------------
  449. // Purpose: Perform conversion. Returns number of *bytes* required if output pointer is NULL.
  450. //-----------------------------------------------------------------------------
  451. int Q_UTF8CharsToUTF32( const char *pUTF8, int nElements, uchar32 *pUTF32, int cubDestSizeInBytes, EStringConvertErrorPolicy ePolicy )
  452. {
  453. return Q_UnicodeConvertT< char, uchar32, false, Q_UTF8ToUChar32, Q_UChar32ToUTF32Len, Q_UChar32ToUTF32 >( pUTF8, nElements, pUTF32, cubDestSizeInBytes, ePolicy );
  454. }
  455. //-----------------------------------------------------------------------------
  456. // Purpose: Perform conversion. Returns number of *bytes* required if output pointer is NULL.
  457. //-----------------------------------------------------------------------------
  458. int Q_UTF16CharsToUTF8( const uchar16 *pUTF16, int nElements, char *pUTF8, int cubDestSizeInBytes, EStringConvertErrorPolicy ePolicy )
  459. {
  460. return Q_UnicodeConvertT< uchar16, char, false, Q_UTF16ToUChar32, Q_UChar32ToUTF8Len, Q_UChar32ToUTF8 >( pUTF16, nElements, pUTF8, cubDestSizeInBytes, ePolicy );
  461. }
  462. //-----------------------------------------------------------------------------
  463. // Purpose: Perform conversion. Returns number of *bytes* required if output pointer is NULL.
  464. //-----------------------------------------------------------------------------
  465. int Q_UTF16CharsToUTF32( const uchar16 *pUTF16, int nElements, uchar32 *pUTF32, int cubDestSizeInBytes, EStringConvertErrorPolicy ePolicy )
  466. {
  467. return Q_UnicodeConvertT< uchar16, uchar32, false, Q_UTF16ToUChar32, Q_UChar32ToUTF32Len, Q_UChar32ToUTF32 >( pUTF16, nElements, pUTF32, cubDestSizeInBytes, ePolicy );
  468. }
  469. //-----------------------------------------------------------------------------
  470. // Purpose: Perform conversion. Returns number of *bytes* required if output pointer is NULL.
  471. //-----------------------------------------------------------------------------
  472. int Q_UTF32CharsToUTF8( const uchar32 *pUTF32, int nElements, char *pUTF8, int cubDestSizeInBytes, EStringConvertErrorPolicy ePolicy )
  473. {
  474. return Q_UnicodeConvertT< uchar32, char, false, Q_UTF32ToUChar32, Q_UChar32ToUTF8Len, Q_UChar32ToUTF8 >( pUTF32, nElements, pUTF8, cubDestSizeInBytes, ePolicy );
  475. }
  476. //-----------------------------------------------------------------------------
  477. // Purpose: Perform conversion. Returns number of *bytes* required if output pointer is NULL.
  478. //-----------------------------------------------------------------------------
  479. int Q_UTF32CharsToUTF16( const uchar32 *pUTF32, int nElements, uchar16 *pUTF16, int cubDestSizeInBytes, EStringConvertErrorPolicy ePolicy )
  480. {
  481. return Q_UnicodeConvertT< uchar32, uchar16, false, Q_UTF32ToUChar32, Q_UChar32ToUTF16Len, Q_UChar32ToUTF16 >( pUTF32, nElements, pUTF16, cubDestSizeInBytes, ePolicy );
  482. }
  483. //-----------------------------------------------------------------------------
  484. // Purpose: Repair a UTF-8 string by removing or replacing invalid seqeuences. Returns non-zero on success.
  485. //-----------------------------------------------------------------------------
  486. int Q_UnicodeRepair( char *pUTF8, EStringConvertErrorPolicy ePolicy )
  487. {
  488. return Q_UnicodeConvertT< char, char, true, Q_UTF8ToUChar32, Q_UChar32ToUTF8Len, Q_UChar32ToUTF8 >( pUTF8, 0, pUTF8, INT_MAX, ePolicy );
  489. }
  490. //-----------------------------------------------------------------------------
  491. // Purpose: Repair a UTF-16 string by removing or replacing invalid seqeuences. Returns non-zero on success.
  492. //-----------------------------------------------------------------------------
  493. int Q_UnicodeRepair( uchar16 *pUTF16, EStringConvertErrorPolicy ePolicy )
  494. {
  495. return Q_UnicodeConvertT< uchar16, uchar16, true, Q_UTF16ToUChar32, Q_UChar32ToUTF16Len, Q_UChar32ToUTF16 >( pUTF16, 0, pUTF16, INT_MAX/sizeof(uchar16), ePolicy );
  496. }
  497. //-----------------------------------------------------------------------------
  498. // Purpose: Repair a UTF-32 string by removing or replacing invalid seqeuences. Returns non-zero on success.
  499. //-----------------------------------------------------------------------------
  500. int Q_UnicodeRepair( uchar32 *pUTF32, EStringConvertErrorPolicy ePolicy )
  501. {
  502. return Q_UnicodeConvertT< uchar32, uchar32, true, Q_UTF32ToUChar32, Q_UChar32ToUTF32Len, Q_UChar32ToUTF32 >( pUTF32, 0, pUTF32, INT_MAX/sizeof(uchar32), ePolicy );
  503. }