2021-08-13 17:21:29 +03:00
// SPDX-License-Identifier: GPL-2.0
/*
*
* Copyright ( C ) 2019 - 2021 Paragon Software GmbH , All rights reserved .
*
*/
2021-08-03 14:57:09 +03:00
2021-09-02 19:15:26 +03:00
# include <linux/kernel.h>
# include <linux/types.h>
2021-08-13 17:21:29 +03:00
# include "ntfs_fs.h"
static inline u16 upcase_unicode_char ( const u16 * upcase , u16 chr )
{
if ( chr < ' a ' )
return chr ;
if ( chr < = ' z ' )
return chr - ( ' a ' - ' A ' ) ;
return upcase [ chr ] ;
}
/*
2021-08-03 14:57:09 +03:00
* ntfs_cmp_names
*
2021-08-13 17:21:29 +03:00
* Thanks Kari Argillander < kari . argillander @ gmail . com > for idea and implementation ' bothcase '
*
2021-08-16 13:13:08 +03:00
* Straight way to compare names :
2021-08-03 14:57:09 +03:00
* - Case insensitive
* - If name equals and ' bothcases ' then
* - Case sensitive
2021-08-31 16:57:40 +03:00
* ' Straight way ' code scans input names twice in worst case .
2021-08-03 14:57:09 +03:00
* Optimized code scans input names only once .
2021-08-13 17:21:29 +03:00
*/
int ntfs_cmp_names ( const __le16 * s1 , size_t l1 , const __le16 * s2 , size_t l2 ,
const u16 * upcase , bool bothcase )
{
int diff1 = 0 ;
int diff2 ;
size_t len = min ( l1 , l2 ) ;
if ( ! bothcase & & upcase )
goto case_insentive ;
for ( ; len ; s1 + + , s2 + + , len - - ) {
diff1 = le16_to_cpu ( * s1 ) - le16_to_cpu ( * s2 ) ;
if ( diff1 ) {
if ( bothcase & & upcase )
goto case_insentive ;
return diff1 ;
}
}
return l1 - l2 ;
case_insentive :
for ( ; len ; s1 + + , s2 + + , len - - ) {
diff2 = upcase_unicode_char ( upcase , le16_to_cpu ( * s1 ) ) -
upcase_unicode_char ( upcase , le16_to_cpu ( * s2 ) ) ;
if ( diff2 )
return diff2 ;
}
diff2 = l1 - l2 ;
return diff2 ? diff2 : diff1 ;
}
int ntfs_cmp_names_cpu ( const struct cpu_str * uni1 , const struct le_str * uni2 ,
const u16 * upcase , bool bothcase )
{
const u16 * s1 = uni1 - > name ;
const __le16 * s2 = uni2 - > name ;
size_t l1 = uni1 - > len ;
size_t l2 = uni2 - > len ;
size_t len = min ( l1 , l2 ) ;
int diff1 = 0 ;
int diff2 ;
if ( ! bothcase & & upcase )
goto case_insentive ;
for ( ; len ; s1 + + , s2 + + , len - - ) {
diff1 = * s1 - le16_to_cpu ( * s2 ) ;
if ( diff1 ) {
if ( bothcase & & upcase )
goto case_insentive ;
return diff1 ;
}
}
return l1 - l2 ;
case_insentive :
for ( ; len ; s1 + + , s2 + + , len - - ) {
diff2 = upcase_unicode_char ( upcase , * s1 ) -
upcase_unicode_char ( upcase , le16_to_cpu ( * s2 ) ) ;
if ( diff2 )
return diff2 ;
}
diff2 = l1 - l2 ;
return diff2 ? diff2 : diff1 ;
}