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