ff_string.c 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784
  1. /*
  2. * FreeRTOS+FAT V2.3.3
  3. * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  4. *
  5. * Permission is hereby granted, free of charge, to any person obtaining a copy of
  6. * this software and associated documentation files (the "Software"), to deal in
  7. * the Software without restriction, including without limitation the rights to
  8. * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
  9. * the Software, and to permit persons to whom the Software is furnished to do so,
  10. * subject to the following conditions:
  11. *
  12. * The above copyright notice and this permission notice shall be included in all
  13. * copies or substantial portions of the Software.
  14. *
  15. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
  17. * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
  18. * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
  19. * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  20. * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  21. *
  22. * https://www.FreeRTOS.org
  23. * https://github.com/FreeRTOS
  24. *
  25. */
  26. /**
  27. * @file ff_string.c
  28. * @ingroup STRING
  29. *
  30. * @defgroup STRING FreeRTOS+FAT String Library
  31. * @brief Portable String Library for FreeRTOS+FAT
  32. *
  33. *
  34. **/
  35. #include <stdlib.h>
  36. #include <string.h>
  37. #include <ctype.h>
  38. #include "ff_headers.h"
  39. #if ( ffconfigUNICODE_UTF16_SUPPORT != 0 )
  40. #include <wchar.h>
  41. #include <wctype.h>
  42. #endif
  43. /*
  44. * These will eventually be moved into a platform independent string
  45. * library. Which will be optional. (To allow the use of system specific versions).
  46. */
  47. #if ( ffconfigUNICODE_UTF16_SUPPORT != 0 )
  48. void FF_cstrntowcs( FF_T_WCHAR * wcsDest,
  49. const char * szpSource,
  50. uint32_t ulLength )
  51. {
  52. while( ( *szpSource != '\0' ) && ( ulLength-- != 0 ) )
  53. {
  54. *( wcsDest++ ) = *( szpSource++ );
  55. }
  56. *wcsDest = '\0';
  57. }
  58. #endif /* ffconfigUNICODE_UTF16_SUPPORT */
  59. /*-----------------------------------------------------------*/
  60. #if ( ffconfigUNICODE_UTF16_SUPPORT != 0 )
  61. void FF_cstrtowcs( FF_T_WCHAR * wcsDest,
  62. const char * szpSource )
  63. {
  64. while( *szpSource != '\0' )
  65. {
  66. *wcsDest++ = ( FF_T_WCHAR ) *( szpSource++ );
  67. }
  68. *wcsDest = '\0';
  69. }
  70. #endif /* ffconfigUNICODE_UTF16_SUPPORT */
  71. /*-----------------------------------------------------------*/
  72. #if ( ffconfigUNICODE_UTF16_SUPPORT != 0 )
  73. void FF_wcstocstr( char * szpDest,
  74. const FF_T_WCHAR * wcsSource )
  75. {
  76. while( *wcsSource != '\0' )
  77. {
  78. *szpDest++ = ( int8_t ) *( wcsSource++ );
  79. }
  80. *szpDest = '\0';
  81. }
  82. #endif /* ffconfigUNICODE_UTF16_SUPPORT */
  83. /*-----------------------------------------------------------*/
  84. #if ( ffconfigUNICODE_UTF16_SUPPORT != 0 )
  85. void FF_wcsntocstr( char * szpDest,
  86. const FF_T_WCHAR * wcsSource,
  87. uint32_t ulLength )
  88. {
  89. while( ( *wcsSource != '\0' ) && ( ulLength-- != 0 ) )
  90. {
  91. *( szpDest++ ) = ( int8_t ) *( wcsSource++ );
  92. }
  93. *szpDest = '\0';
  94. }
  95. #endif /* ffconfigUNICODE_UTF16_SUPPORT */
  96. /*-----------------------------------------------------------*/
  97. /*-----------------------------------------------------------*/
  98. #if ( ffconfigUNICODE_UTF16_SUPPORT != 0 )
  99. void FF_toupper( FF_T_WCHAR * string,
  100. uint32_t ulLength )
  101. {
  102. uint32_t i;
  103. for( i = 0; i < ulLength; i++ )
  104. {
  105. string[ i ] = towupper( string[ i ] );
  106. }
  107. }
  108. /*-----------------------------------------------------------*/
  109. void FF_tolower( FF_T_WCHAR * string,
  110. uint32_t ulLength )
  111. {
  112. uint32_t i;
  113. for( i = 0; i < ulLength; i++ )
  114. {
  115. string[ i ] = towlower( string[ i ] );
  116. }
  117. }
  118. /*-----------------------------------------------------------*/
  119. #else /* ffconfigUNICODE_UTF16_SUPPORT */
  120. void FF_toupper( char * string,
  121. uint32_t ulLength )
  122. {
  123. uint32_t i;
  124. for( i = 0; i < ulLength; i++ )
  125. {
  126. if( ( string[ i ] >= 'a' ) && ( string[ i ] <= 'z' ) )
  127. {
  128. string[ i ] -= 32;
  129. }
  130. if( string[ i ] == '\0' )
  131. {
  132. break;
  133. }
  134. }
  135. }
  136. /*-----------------------------------------------------------*/
  137. void FF_tolower( char * string,
  138. uint32_t ulLength )
  139. {
  140. uint32_t i;
  141. for( i = 0; i < ulLength; i++ )
  142. {
  143. if( ( string[ i ] >= 'A' ) && ( string[ i ] <= 'Z' ) )
  144. {
  145. string[ i ] += 32;
  146. }
  147. if( string[ i ] == '\0' )
  148. {
  149. break;
  150. }
  151. }
  152. }
  153. /*-----------------------------------------------------------*/
  154. #endif /* ffconfigUNICODE_UTF16_SUPPORT */
  155. /**
  156. * @private
  157. * @brief Compares 2 strings for the specified length, and returns pdTRUE is they are identical
  158. * otherwise pdFALSE is returned.
  159. *
  160. **/
  161. #if ( ffconfigUNICODE_UTF16_SUPPORT == 0 )
  162. BaseType_t FF_strmatch( const char * str1,
  163. const char * str2,
  164. BaseType_t xLength )
  165. {
  166. register BaseType_t i;
  167. register char char1, char2;
  168. if( xLength == 0 )
  169. {
  170. xLength = strlen( str1 );
  171. if( xLength != ( BaseType_t ) strlen( str2 ) )
  172. {
  173. return pdFALSE;
  174. }
  175. }
  176. for( i = 0; i < xLength; i++ )
  177. {
  178. char1 = str1[ i ];
  179. char2 = str2[ i ];
  180. if( ( char1 >= 'A' ) && ( char1 <= 'Z' ) )
  181. {
  182. char1 += 32;
  183. }
  184. if( ( char2 >= 'A' ) && ( char2 <= 'Z' ) )
  185. {
  186. char2 += 32;
  187. }
  188. if( char1 != char2 )
  189. {
  190. return pdFALSE;
  191. }
  192. }
  193. return pdTRUE;
  194. }
  195. #else /* ffconfigUNICODE_UTF16_SUPPORT */
  196. BaseType_t FF_strmatch( const FF_T_WCHAR * str1,
  197. const FF_T_WCHAR * str2,
  198. BaseType_t xLength )
  199. {
  200. register BaseType_t i;
  201. register FF_T_WCHAR char1, char2;
  202. if( xLength == 0 )
  203. {
  204. xLength = wcslen( str1 );
  205. if( xLength != wcslen( str2 ) )
  206. {
  207. return pdFALSE;
  208. }
  209. }
  210. for( i = 0; i < xLength; i++ )
  211. {
  212. char1 = towlower( str1[ i ] );
  213. char2 = towlower( str2[ i ] );
  214. if( char1 != char2 )
  215. {
  216. return pdFALSE;
  217. }
  218. }
  219. return pdTRUE;
  220. }
  221. #endif /* ffconfigUNICODE_UTF16_SUPPORT */
  222. /**
  223. * @private
  224. * @brief A re-entrant Strtok function. No documentation is provided :P
  225. * Use at your own risk. (This is for FreeRTOS+FAT's use only).
  226. **/
  227. #if ( ffconfigUNICODE_UTF16_SUPPORT == 0 )
  228. char * FF_strtok( const char * string,
  229. char * token,
  230. uint16_t * tokenNumber,
  231. BaseType_t * last,
  232. BaseType_t xLength )
  233. {
  234. uint16_t i, y, tokenStart, tokenEnd = 0;
  235. i = 0;
  236. y = 0;
  237. if( ( string[ i ] == '\\' ) || ( string[ i ] == '/' ) )
  238. {
  239. i++;
  240. }
  241. tokenStart = i;
  242. while( i < xLength )
  243. {
  244. if( ( string[ i ] == '\\' ) || ( string[ i ] == '/' ) )
  245. {
  246. y++;
  247. if( y == *tokenNumber )
  248. {
  249. tokenStart = ( uint16_t ) ( i + 1 );
  250. }
  251. if( y == ( *tokenNumber + 1 ) )
  252. {
  253. tokenEnd = i;
  254. break;
  255. }
  256. }
  257. i++;
  258. }
  259. if( tokenEnd == 0 )
  260. {
  261. if( *last == pdTRUE )
  262. {
  263. return NULL;
  264. }
  265. else
  266. {
  267. *last = pdTRUE;
  268. }
  269. tokenEnd = i;
  270. }
  271. if( ( tokenEnd - tokenStart ) < ffconfigMAX_FILENAME )
  272. {
  273. memcpy( token, ( string + tokenStart ), ( uint32_t ) ( tokenEnd - tokenStart ) );
  274. token[ tokenEnd - tokenStart ] = '\0';
  275. }
  276. else
  277. {
  278. memcpy( token, ( string + tokenStart ), ( uint32_t ) ( ffconfigMAX_FILENAME ) );
  279. token[ ffconfigMAX_FILENAME - 1 ] = '\0';
  280. }
  281. /*token[tokenEnd - tokenStart] = '\0'; */
  282. *tokenNumber += 1;
  283. return token;
  284. }
  285. #else /* ffconfigUNICODE_UTF16_SUPPORT */
  286. FF_T_WCHAR * FF_strtok( const FF_T_WCHAR * string,
  287. FF_T_WCHAR * token,
  288. uint16_t * tokenNumber,
  289. BaseType_t * last,
  290. BaseType_t xLength )
  291. {
  292. uint16_t i, y, tokenStart, tokenEnd = 0;
  293. i = 0;
  294. y = 0;
  295. if( ( string[ i ] == '\\' ) || ( string[ i ] == '/' ) )
  296. {
  297. i++;
  298. }
  299. tokenStart = i;
  300. while( i < xLength )
  301. {
  302. if( ( string[ i ] == '\\' ) || ( string[ i ] == '/' ) )
  303. {
  304. y++;
  305. if( y == *tokenNumber )
  306. {
  307. tokenStart = ( uint16_t ) ( i + 1 );
  308. }
  309. if( y == ( *tokenNumber + 1 ) )
  310. {
  311. tokenEnd = i;
  312. break;
  313. }
  314. }
  315. i++;
  316. }
  317. if( tokenEnd == 0 )
  318. {
  319. if( *last == pdTRUE )
  320. {
  321. return NULL;
  322. }
  323. else
  324. {
  325. *last = pdTRUE;
  326. }
  327. tokenEnd = i;
  328. }
  329. if( ( tokenEnd - tokenStart ) < ffconfigMAX_FILENAME )
  330. {
  331. memcpy( token, ( string + tokenStart ), ( uint32_t ) ( tokenEnd - tokenStart ) * sizeof( FF_T_WCHAR ) );
  332. token[ tokenEnd - tokenStart ] = '\0';
  333. }
  334. else
  335. {
  336. memcpy( token, ( string + tokenStart ), ( uint32_t ) ( ffconfigMAX_FILENAME ) * sizeof( FF_T_WCHAR ) );
  337. token[ ffconfigMAX_FILENAME - 1 ] = '\0';
  338. }
  339. /*token[tokenEnd - tokenStart] = '\0'; */
  340. *tokenNumber += 1;
  341. return token;
  342. }
  343. #endif /* ffconfigUNICODE_UTF16_SUPPORT */
  344. /* UTF-8 Routines */
  345. /*
  346. * UCS-4 range (hex.) UTF-8 octet sequence (binary)
  347. * 0000 0000-0000 007F 0xxxxxxx
  348. * 0000 0080-0000 07FF 110xxxxx 10xxxxxx
  349. * 0000 0800-0000 FFFF 1110xxxx 10xxxxxx 10xxxxxx
  350. *
  351. * 0001 0000-001F FFFF 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
  352. * 0020 0000-03FF FFFF 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx -- We don't encode these because we won't receive them. (Invalid UNICODE).
  353. * 0400 0000-7FFF FFFF 1111110x 10xxxxxx ... 10xxxxxx -- We don't encode these because we won't receive them. (Invalid UNICODE).
  354. */
  355. #if ( ( ffconfigUNICODE_UTF16_SUPPORT != 0 ) && ( WCHAR_MAX > 0xFFFF ) ) || ( ffconfigUNICODE_UTF8_SUPPORT != 0 )
  356. UBaseType_t FF_GetUtf16SequenceLen( uint16_t usLeadChar )
  357. {
  358. UBaseType_t uxReturn;
  359. if( ( usLeadChar & 0xFC00 ) == 0xD800 )
  360. {
  361. uxReturn = 2;
  362. }
  363. else
  364. {
  365. uxReturn = 1;
  366. }
  367. return uxReturn;
  368. } /* FF_GetUtf16SequenceLen() */
  369. #endif /* if ( ( ffconfigUNICODE_UTF16_SUPPORT != 0 ) && ( WCHAR_MAX > 0xFFFF ) ) || ( ffconfigUNICODE_UTF8_SUPPORT != 0 ) */
  370. /*-----------------------------------------------------------*/
  371. /*
  372. * Returns the number of UTF-8 units read.
  373. * Will not exceed ulSize UTF-16 units. (ulSize * 2 bytes).
  374. */
  375. /*
  376. * UCS-4 range (hex.) UTF-8 octet sequence (binary)
  377. * 0000 0000-0000 007F 0xxxxxxx
  378. * 0000 0080-0000 07FF 110xxxxx 10xxxxxx
  379. * 0000 0800-0000 FFFF 1110xxxx 10xxxxxx 10xxxxxx
  380. *
  381. * 0001 0000-001F FFFF 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
  382. * 0020 0000-03FF FFFF 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx -- We don't encode these because we won't receive them. (Invalid UNICODE).
  383. * 0400 0000-7FFF FFFF 1111110x 10xxxxxx ... 10xxxxxx -- We don't encode these because we won't receive them. (Invalid UNICODE).
  384. */
  385. #if ( ffconfigUNICODE_UTF8_SUPPORT != 0 )
  386. int32_t FF_Utf8ctoUtf16c( uint16_t * utf16Dest,
  387. const uint8_t * utf8Source,
  388. uint32_t ulSize )
  389. {
  390. uint32_t ulUtf32char;
  391. uint16_t utf16Source = 0;
  392. register int32_t lSequenceNumber = 0;
  393. /* Count number of set bits before a zero. */
  394. while( ( *utf8Source != '\0' ) && (*utf8Source & ( 0x80 >> ( lSequenceNumber ) ) ) ) // ZJH modification
  395. {
  396. lSequenceNumber++;
  397. }
  398. if( lSequenceNumber == 0UL )
  399. {
  400. lSequenceNumber++;
  401. }
  402. if( ulSize == 0UL )
  403. {
  404. /* Returned value becomes an error, with the highest bit set. */
  405. lSequenceNumber = FF_ERR_UNICODE_DEST_TOO_SMALL | FF_UTF8CTOUTF16C;
  406. }
  407. else
  408. {
  409. switch( lSequenceNumber )
  410. {
  411. case 1:
  412. utf16Source = ( uint16_t ) *utf8Source;
  413. memcpy( utf16Dest, &utf16Source, sizeof( uint16_t ) );
  414. break;
  415. case 2:
  416. utf16Source = ( uint16_t ) ( ( *utf8Source & 0x1F ) << 6 ) | ( ( *( utf8Source + 1 ) & 0x3F ) );
  417. memcpy( utf16Dest, &utf16Source, sizeof( uint16_t ) );
  418. break;
  419. case 3:
  420. utf16Source = ( uint16_t ) ( ( *utf8Source & 0x0F ) << 12 ) | ( ( *( utf8Source + 1 ) & 0x3F ) << 6 ) | ( ( *( utf8Source + 2 ) & 0x3F ) );
  421. memcpy( utf16Dest, &utf16Source, sizeof( uint16_t ) );
  422. break;
  423. case 4:
  424. if( ulSize < 2 )
  425. {
  426. /* Returned value becomes an error. */
  427. lSequenceNumber = FF_ERR_UNICODE_DEST_TOO_SMALL | FF_UTF8CTOUTF16C;
  428. }
  429. else
  430. {
  431. /* Convert to UTF-32 and then into UTF-16 */
  432. ulUtf32char = ( uint16_t )
  433. ( ( *utf8Source & 0x0F ) << 18 ) |
  434. ( ( *( utf8Source + 1 ) & 0x3F ) << 12 ) |
  435. ( ( *( utf8Source + 2 ) & 0x3F ) << 6 ) |
  436. ( ( *( utf8Source + 3 ) & 0x3F ) );
  437. utf16Source = ( uint16_t ) ( ( ( ulUtf32char - 0x10000 ) & 0xFFC00 ) >> 10 ) | 0xD800;
  438. memcpy( utf16Dest, &utf16Source, sizeof( uint16_t ) );
  439. utf16Source = ( uint16_t ) ( ( ( ulUtf32char - 0x10000 ) & 0x003FF ) >> 00 ) | 0xDC00;
  440. memcpy( utf16Dest + 1, &utf16Source, sizeof( uint16_t ) );
  441. }
  442. break;
  443. default:
  444. break;
  445. }
  446. }
  447. return lSequenceNumber;
  448. } /* FF_Utf8ctoUtf16c() */
  449. #endif /* ffconfigUNICODE_UTF8_SUPPORT */
  450. /*-----------------------------------------------------------*/
  451. /*
  452. * Returns the number of UTF-8 units required to encode the UTF-16 sequence.
  453. * Will not exceed ulSize UTF-8 units. (ulSize * 1 bytes).
  454. */
  455. #if ( ffconfigUNICODE_UTF8_SUPPORT != 0 )
  456. int32_t FF_Utf16ctoUtf8c( uint8_t * utf8Dest,
  457. const uint16_t * utf16Source,
  458. uint32_t ulSize )
  459. {
  460. uint32_t ulUtf32char;
  461. uint16_t ulUtf16char;
  462. int32_t lReturn = 0L;
  463. do
  464. {
  465. if( ulSize == 0UL )
  466. {
  467. lReturn = FF_ERR_UNICODE_DEST_TOO_SMALL | FF_UTF16CTOUTF8C;
  468. break;
  469. }
  470. memcpy( &ulUtf16char, utf16Source, sizeof( uint16_t ) );
  471. /* A surrogate sequence was encountered. Must transform to UTF32 first. */
  472. if( ( ulUtf16char & 0xF800 ) == 0xD800 )
  473. {
  474. ulUtf32char = ( ( uint32_t ) ( ulUtf16char & 0x003FF ) << 10 ) + 0x10000;
  475. memcpy( &ulUtf16char, utf16Source + 1, sizeof( uint16_t ) );
  476. if( ( ulUtf16char & 0xFC00 ) != 0xDC00 )
  477. {
  478. /* Invalid UTF-16 sequence. */
  479. lReturn = FF_ERR_UNICODE_INVALID_SEQUENCE | FF_UTF16CTOUTF8C;
  480. break;
  481. }
  482. ulUtf32char |= ( ( uint32_t ) ( ulUtf16char & 0x003FF ) );
  483. }
  484. else
  485. {
  486. ulUtf32char = ( uint32_t ) ulUtf16char;
  487. }
  488. /* Now convert to the UTF-8 sequence. */
  489. /* Single byte UTF-8 sequence. */
  490. if( ulUtf32char < 0x00000080 )
  491. {
  492. *( utf8Dest + 0 ) = ( uint8_t ) ulUtf32char;
  493. lReturn = 1;
  494. break;
  495. }
  496. /* Double byte UTF-8 sequence. */
  497. if( ulUtf32char < 0x00000800 )
  498. {
  499. if( ulSize < 2 )
  500. {
  501. lReturn = FF_ERR_UNICODE_DEST_TOO_SMALL | FF_UTF16CTOUTF8C;
  502. }
  503. else
  504. {
  505. *( utf8Dest + 0 ) = ( uint8_t ) ( 0xC0 | ( ( ulUtf32char >> 6 ) & 0x1F ) );
  506. *( utf8Dest + 1 ) = ( uint8_t ) ( 0x80 | ( ( ulUtf32char >> 0 ) & 0x3F ) );
  507. lReturn = 2;
  508. }
  509. break;
  510. }
  511. /* Triple byte UTF-8 sequence. */
  512. if( ulUtf32char < 0x00010000 )
  513. {
  514. if( ulSize < 3 )
  515. {
  516. lReturn = FF_ERR_UNICODE_DEST_TOO_SMALL | FF_UTF16CTOUTF8C;
  517. }
  518. else
  519. {
  520. *( utf8Dest + 0 ) = ( uint8_t ) ( 0xE0 | ( ( ulUtf32char >> 12 ) & 0x0F ) );
  521. *( utf8Dest + 1 ) = ( uint8_t ) ( 0x80 | ( ( ulUtf32char >> 6 ) & 0x3F ) );
  522. *( utf8Dest + 2 ) = ( uint8_t ) ( 0x80 | ( ( ulUtf32char >> 0 ) & 0x3F ) );
  523. lReturn = 3;
  524. }
  525. break;
  526. }
  527. /* Quadruple byte UTF-8 sequence. */
  528. if( ulUtf32char < 0x00200000 )
  529. {
  530. if( ulSize < 4 )
  531. {
  532. lReturn = FF_ERR_UNICODE_DEST_TOO_SMALL | FF_UTF16CTOUTF8C;
  533. }
  534. else
  535. {
  536. *( utf8Dest + 0 ) = ( uint8_t ) ( 0xF0 | ( ( ulUtf32char >> 18 ) & 0x07 ) );
  537. *( utf8Dest + 1 ) = ( uint8_t ) ( 0x80 | ( ( ulUtf32char >> 12 ) & 0x3F ) );
  538. *( utf8Dest + 2 ) = ( uint8_t ) ( 0x80 | ( ( ulUtf32char >> 6 ) & 0x3F ) );
  539. *( utf8Dest + 3 ) = ( uint8_t ) ( 0x80 | ( ( ulUtf32char >> 0 ) & 0x3F ) );
  540. lReturn = 4;
  541. }
  542. break;
  543. }
  544. lReturn = FF_ERR_UNICODE_INVALID_CODE | FF_UTF16CTOUTF8C; /* Invalid Character */
  545. }
  546. while( pdFALSE );
  547. return lReturn;
  548. } /* FF_Utf16ctoUtf8c() */
  549. #endif /* ffconfigUNICODE_UTF8_SUPPORT */
  550. /*-----------------------------------------------------------*/
  551. /* UTF-16 Support Functions */
  552. /* Converts a UTF-32 Character into its equivalent UTF-16 sequence. */
  553. #if ( ffconfigUNICODE_UTF16_SUPPORT != 0 ) && ( WCHAR_MAX > 0xFFFF )
  554. int32_t FF_Utf32ctoUtf16c( uint16_t * utf16Dest,
  555. uint32_t utf32char,
  556. uint32_t ulSize )
  557. {
  558. int32_t lReturn;
  559. /* Check that its a valid UTF-32 wide-char! */
  560. /* This range is not a valid Unicode code point. */
  561. if( ( utf32char >= 0xD800 ) && ( utf32char <= 0xDFFF ) )
  562. {
  563. lReturn = FF_ERR_UNICODE_INVALID_CODE | FF_UTF32CTOUTF16C; /* Invalid character. */
  564. }
  565. else if( utf32char < 0x10000 )
  566. {
  567. *utf16Dest = ( uint16_t ) utf32char; /* Simple conversion! Char comes within UTF-16 space (without surrogates). */
  568. lReturn = 1;
  569. }
  570. else if( ulSize < 2 )
  571. {
  572. lReturn = FF_ERR_UNICODE_DEST_TOO_SMALL | FF_UTF32CTOUTF16C; /* Not enough UTF-16 units to record this character. */
  573. }
  574. else if( utf32char < 0x00200000 )
  575. {
  576. /* Conversion to a UTF-16 Surrogate pair! */
  577. /*valueImage = utf32char - 0x10000; */
  578. *( utf16Dest + 0 ) = ( uint16_t ) ( ( ( utf32char - 0x10000 ) & 0xFFC00 ) >> 10 ) | 0xD800;
  579. *( utf16Dest + 1 ) = ( uint16_t ) ( ( ( utf32char - 0x10000 ) & 0x003FF ) >> 00 ) | 0xDC00;
  580. lReturn = 2; /* Surrogate pair encoded value. */
  581. }
  582. else
  583. {
  584. /* Invalid Character */
  585. lReturn = FF_ERR_UNICODE_INVALID_CODE | FF_UTF32CTOUTF16C;
  586. }
  587. return lReturn;
  588. } /* FF_Utf32ctoUtf16c() */
  589. #endif /* #if( ffconfigUNICODE_UTF16_SUPPORT != 0 ) && ( WCHAR_MAX > 0xFFFF ) */
  590. /*-----------------------------------------------------------*/
  591. /* Converts a UTF-16 sequence into its equivalent UTF-32 code point. */
  592. #if ( ffconfigNOT_USED_FOR_NOW != 0 )
  593. int32_t FF_Utf16ctoUtf32c( uint32_t * utf32Dest,
  594. const uint16_t * utf16Source )
  595. {
  596. int32_t lReturn;
  597. /*Not a surrogate sequence. */
  598. if( ( *utf16Source & 0xFC00 ) != 0xD800 )
  599. {
  600. *utf32Dest = ( uint32_t ) *utf16Source;
  601. lReturn = 1; /* A single UTF-16 item was used to represent the character. */
  602. }
  603. else
  604. {
  605. *utf32Dest = ( ( uint32_t ) ( *( utf16Source + 0 ) & 0x003FF ) << 10 ) + 0x10000;
  606. if( ( *( utf16Source + 1 ) & 0xFC00 ) != 0xDC00 )
  607. {
  608. lReturn = FF_ERR_UNICODE_INVALID_SEQUENCE | FF_UTF16CTOUTF32C; /* Invalid UTF-16 sequence. */
  609. }
  610. else
  611. {
  612. *utf32Dest |= ( ( uint32_t ) ( *( utf16Source + 1 ) & 0x003FF ) );
  613. lReturn = 2; /* 2 utf-16 units make up the Unicode code-point. */
  614. }
  615. }
  616. return lReturn;
  617. } /* FF_Utf16ctoUtf32c() */
  618. #endif /* ffconfigNOT_USED_FOR_NOW */
  619. /*-----------------------------------------------------------*/
  620. /*
  621. * Returns the total number of UTF-16 items required to represent
  622. * the provided UTF-32 string in UTF-16 form.
  623. */
  624. /*
  625. * UBaseType_t FF_Utf32GetUtf16Len( const uint32_t *utf32String )
  626. * {
  627. * UBaseType_t utf16len = 0;
  628. *
  629. * while( *utf32String )
  630. * {
  631. * if( *utf32String++ <= 0xFFFF )
  632. * {
  633. * utf16len++;
  634. * }
  635. * else
  636. * {
  637. * utf16len += 2;
  638. * }
  639. * }
  640. *
  641. * return utf16len;
  642. * }
  643. */
  644. /*-----------------------------------------------------------*/
  645. /* String conversions */
  646. #if ( ffconfigNOT_USED_FOR_NOW != 0 )
  647. int32_t FF_Utf32stoUtf8s( uint8_t * Utf8String,
  648. uint32_t * Utf32String )
  649. {
  650. int i = 0, y = 0;
  651. uint16_t utf16buffer[ 2 ];
  652. while( Utf32String[ i ] != '\0' )
  653. {
  654. /* Convert to a UTF16 char. */
  655. FF_Utf32ctoUtf16c( utf16buffer, Utf32String[ i ], 2 );
  656. /* Now convert the UTF16 to UTF8 sequence. */
  657. y += FF_Utf16ctoUtf8c( &Utf8String[ y ], utf16buffer, 4 );
  658. i++;
  659. }
  660. Utf8String[ y ] = '\0';
  661. return 0;
  662. } /* FF_Utf32stoUtf8s() */
  663. #endif /* ffconfigNOT_USED_FOR_NOW */
  664. /*-----------------------------------------------------------*/