1 /*****************************************************************************
2 * FullFAT - High Performance, Thread-Safe Embedded FAT File-System *
3 * Copyright (C) 2009 James Walmsley (james@worm.me.uk) *
5 * This program is free software: you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation, either version 3 of the License, or *
8 * (at your option) any later version. *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program. If not, see <http://www.gnu.org/licenses/>. *
20 * Alternative Licensing is available directly from the Copyright holder, *
21 * (James Walmsley). For more information consult LICENSING.TXT to obtain *
22 * a Commercial license. *
24 * See RESTRICTIONS.TXT for extra restrictions on the use of FullFAT. *
26 * Removing the above notice is illegal and will invalidate this license. *
27 *****************************************************************************
28 * See http://worm.me.uk/fullfat for more information. *
29 * Or http://fullfat.googlecode.com/ for latest releases and the wiki. *
30 *****************************************************************************/
34 * @author James Walmsley
37 * @defgroup STRING FullFAT String Library
38 * @brief Portable String Library for FullFAT
46 #include "ff_string.h"
49 #ifdef FF_UNICODE_SUPPORT
55 * These will eventually be moved into a platform independent string
56 * library. Which will be optional. (To allow the use of system specific versions).
59 #ifdef FF_UNICODE_SUPPORT
61 void FF_cstrntowcs(FF_T_WCHAR
*wcsDest
, const FF_T_INT8
*szpSource
, FF_T_UINT32 len
) {
62 while(*szpSource
&& len
--) {
63 *wcsDest
++ = *szpSource
++;
68 void FF_cstrtowcs(FF_T_WCHAR
*wcsDest
, const FF_T_INT8
*szpSource
) {
70 *wcsDest
++ = (FF_T_WCHAR
) *szpSource
++;
75 void FF_wcstocstr(FF_T_INT8
*szpDest
, const FF_T_WCHAR
*wcsSource
) {
77 *szpDest
++ = (FF_T_INT8
) *wcsSource
++;
82 void FF_wcsntocstr(FF_T_INT8
*szpDest
, const FF_T_WCHAR
*wcsSource
, FF_T_UINT32 len
) {
83 while(*wcsSource
&& len
--) {
84 *szpDest
++ = (FF_T_INT8
) *wcsSource
++;
93 * @brief Converts an ASCII string to lowercase.
95 #ifndef FF_UNICODE_SUPPORT
98 * @brief Converts an ASCII string to uppercase.
100 void FF_toupper(FF_T_INT8
*string
, FF_T_UINT32 strLen
) {
102 for(i
= 0; i
< strLen
; i
++) {
103 if(string
[i
] >= 'a' && string
[i
] <= 'z')
105 if(string
[i
] == '\0')
109 void FF_tolower(FF_T_INT8
*string
, FF_T_UINT32 strLen
) {
111 for(i
= 0; i
< strLen
; i
++) {
112 if(string
[i
] >= 'A' && string
[i
] <= 'Z')
114 if(string
[i
] == '\0')
120 void FF_toupper(FF_T_WCHAR
*string
, FF_T_UINT32 strLen
) {
122 for(i
= 0; i
< strLen
; i
++) {
123 string
[i
] = towupper(string
[i
]);
126 void FF_tolower(FF_T_WCHAR
*string
, FF_T_UINT32 strLen
) {
128 for(i
= 0; i
< strLen
; i
++) {
129 string
[i
] = towlower(string
[i
]);
139 * @brief Compares 2 strings for the specified length, and returns FF_TRUE is they are identical
140 * otherwise FF_FALSE is returned.
144 #ifndef FF_UNICODE_SUPPORT
145 FF_T_BOOL
FF_strmatch(const FF_T_INT8
*str1
, const FF_T_INT8
*str2
, FF_T_UINT16 len
) {
146 register FF_T_UINT16 i
;
147 register FF_T_INT8 char1
, char2
;
150 if(strlen(str1
) != strlen(str2
)) {
153 len
= (FF_T_UINT16
) strlen(str1
);
156 for(i
= 0; i
< len
; i
++) {
159 if(char1
>= 'A' && char1
<= 'Z') {
162 if(char2
>= 'A' && char2
<= 'Z') {
175 FF_T_BOOL
FF_strmatch(const FF_T_WCHAR
*str1
, const FF_T_WCHAR
*str2
, FF_T_UINT16 len
) {
176 register FF_T_UINT16 i
;
177 register FF_T_WCHAR char1
, char2
;
180 if(wcslen(str1
) != wcslen(str2
)) {
183 len
= (FF_T_UINT16
) wcslen(str1
);
186 for(i
= 0; i
< len
; i
++) {
187 char1
= towlower(str1
[i
]);
188 char2
= towlower(str2
[i
]);
200 * @brief A re-entrant Strtok function. No documentation is provided :P
201 * Use at your own risk. (This is for FullFAT's use only).
204 #ifndef FF_UNICODE_SUPPORT
205 FF_T_INT8
*FF_strtok(const FF_T_INT8
*string
, FF_T_INT8
*token
, FF_T_UINT16
*tokenNumber
, FF_T_BOOL
*last
, FF_T_UINT16 Length
) {
206 FF_T_UINT16 strLen
= Length
;
207 FF_T_UINT16 i
,y
, tokenStart
, tokenEnd
= 0;
212 if(string
[i
] == '\\' || string
[i
] == '/') {
219 if(string
[i
] == '\\' || string
[i
] == '/') {
221 if(y
== *tokenNumber
) {
222 tokenStart
= (FF_T_UINT16
)(i
+ 1);
224 if(y
== (*tokenNumber
+ 1)) {
233 if(*last
== FF_TRUE
) {
240 if((tokenEnd
- tokenStart
) < FF_MAX_FILENAME
) {
241 memcpy(token
, (string
+ tokenStart
), (FF_T_UINT32
)(tokenEnd
- tokenStart
));
242 token
[tokenEnd
- tokenStart
] = '\0';
244 memcpy(token
, (string
+ tokenStart
), (FF_T_UINT32
)(FF_MAX_FILENAME
));
245 token
[FF_MAX_FILENAME
-1] = '\0';
247 //token[tokenEnd - tokenStart] = '\0';
254 FF_T_WCHAR
*FF_strtok(const FF_T_WCHAR
*string
, FF_T_WCHAR
*token
, FF_T_UINT16
*tokenNumber
, FF_T_BOOL
*last
, FF_T_UINT16 Length
) {
255 FF_T_UINT16 strLen
= Length
;
256 FF_T_UINT16 i
,y
, tokenStart
, tokenEnd
= 0;
261 if(string
[i
] == '\\' || string
[i
] == '/') {
268 if(string
[i
] == '\\' || string
[i
] == '/') {
270 if(y
== *tokenNumber
) {
271 tokenStart
= (FF_T_UINT16
)(i
+ 1);
273 if(y
== (*tokenNumber
+ 1)) {
282 if(*last
== FF_TRUE
) {
289 if((tokenEnd
- tokenStart
) < FF_MAX_FILENAME
) {
290 memcpy(token
, (string
+ tokenStart
), (FF_T_UINT32
)(tokenEnd
- tokenStart
) * sizeof(FF_T_WCHAR
));
291 token
[tokenEnd
- tokenStart
] = '\0';
293 memcpy(token
, (string
+ tokenStart
), (FF_T_UINT32
)(FF_MAX_FILENAME
) * sizeof(FF_T_WCHAR
));
294 token
[FF_MAX_FILENAME
-1] = '\0';
296 //token[tokenEnd - tokenStart] = '\0';
304 A Wild-Card Comparator Library function, Provided by Adam Fullerton.
305 This can be extended or altered to improve or advance wildCard matching
306 of the FF_FindFirst() and FF_FindNext() API's.
308 #ifdef FF_FINDAPI_ALLOW_WILDCARDS
309 /*FF_T_BOOL FF_wildcompare(const FF_T_INT8 *pszWildCard, const FF_T_INT8 *pszString) {
310 // Check to see if the string contains the wild card
311 if (!memchr(pszWildCard, '*', strlen(pszWildCard)))
313 // if it does not then do a straight string compare
314 if (strcmp(pszWildCard, pszString))
321 while ((*pszWildCard)
324 // Test for the wild card
325 if (*pszWildCard == '*')
328 while (*pszWildCard == '*')
332 // If there are more chars in the string
335 // Search for the next char
336 pszString = memchr(pszString, (int)*pszWildCard, strlen(pszString));
337 // if it does not exist then the strings don't match
359 // Fail if they don't match
360 if (*pszWildCard != *pszString)
365 // Bump both pointers
369 // fail if different lengths
370 if (*pszWildCard != *pszString)
379 This is a better Wild-card compare function, that works perfectly, and is much more efficient.
380 This function was contributed by one of our commercial customers.
382 #ifdef FF_UNICODE_SUPPORT
383 FF_T_BOOL
FF_wildcompare(const FF_T_WCHAR
*pszWildCard
, const FF_T_WCHAR
*pszString
) {
384 register const FF_T_WCHAR
*pszWc
= NULL
;
385 register const FF_T_WCHAR
*pszStr
= NULL
; // Encourage the string pointers to be placed in memory.
387 if ( *pszWildCard
== '*' ) {
388 while(*(1 + pszWildCard
++) == '*'); // Eat up multiple '*''s
389 pszWc
= (pszWildCard
- 1);
392 if (*pszWildCard
== '?' && !*pszString
) {
393 return FF_FALSE
; // False when the string is ended, yet a ? charachter is demanded.
395 #ifdef FF_WILDCARD_CASE_INSENSITIVE
396 if (*pszWildCard
!= '?' && tolower(*pszWildCard
) != tolower(*pszString
)) {
398 if (*pszWildCard
!= '?' && *pszWildCard
!= *pszString
) {
404 pszString
= pszStr
++;
406 } while ( *pszWildCard
++ && *pszString
++ );
408 while(*pszWildCard
== '*') {
412 if(!*(pszWildCard
- 1)) { // WildCard is at the end. (Terminated)
413 return FF_TRUE
; // Therefore this must be a match.
416 return FF_FALSE
; // If not, then return FF_FALSE!
419 FF_T_BOOL
FF_wildcompare(const FF_T_INT8
*pszWildCard
, const FF_T_INT8
*pszString
) {
420 register const FF_T_INT8
*pszWc
= NULL
;
421 register const FF_T_INT8
*pszStr
= NULL
; // Encourage the string pointers to be placed in memory.
423 if ( *pszWildCard
== '*' ) {
424 while(*(1 + pszWildCard
++) == '*'); // Eat up multiple '*''s
425 pszWc
= (pszWildCard
- 1);
428 if (*pszWildCard
== '?' && !*pszString
) {
429 return FF_FALSE
; // False when the string is ended, yet a ? charachter is demanded.
431 #ifdef FF_WILDCARD_CASE_INSENSITIVE
432 if (*pszWildCard
!= '?' && tolower(*pszWildCard
) != tolower(*pszString
)) {
434 if (*pszWildCard
!= '?' && *pszWildCard
!= *pszString
) {
440 pszString
= pszStr
++;
442 } while ( *pszWildCard
++ && *pszString
++ );
444 while(*pszWildCard
== '*') {
448 if(!*(pszWildCard
- 1)) { // WildCard is at the end. (Terminated)
449 return FF_TRUE
; // Therefore this must be a match.
452 return FF_FALSE
; // If not, then return FF_FALSE!