xref: /reactos/sdk/lib/ucrt/string/wcsicmp.cpp (revision 04e0dc4a)
1 /***
2 *wcsicmp.cpp - contains case-insensitive wide string comp routine _wcsicmp
3 *
4 *       Copyright (c) Microsoft Corporation. All rights reserved.
5 *
6 *Purpose:
7 *       contains _wcsicmp()
8 *
9 *******************************************************************************/
10 #include <corecrt_internal.h>
11 #include <ctype.h>
12 #include <locale.h>
13 #include <string.h>
14 
15 #pragma warning(disable:__WARNING_POTENTIAL_BUFFER_OVERFLOW_NULLTERMINATED) // 26018 Prefast can't see that we are checking for terminal nul.
16 
17 /***
18 *int _wcsicmp(lhs, rhs) - compare wide-character strings, ignore case
19 *
20 *Purpose:
21 *       _wcsicmp performs a case-insensitive wchar_t string comparision.
22 *       _wcsicmp is independent of locale.
23 *
24 *Entry:
25 *       wchar_t *lhs, *rhs - strings to compare
26 *
27 *Return:
28 *       Returns <0 if lhs < rhs
29 *       Returns 0 if lhs = rhs
30 *       Returns >0 if lhs > rhs
31 *       Returns _NLSCMPERROR if something went wrong
32 *       This range of return values may differ from other *cmp/*coll functions.
33 *
34 *Exceptions:
35 *       Input parameters are validated. Refer to the validation section of the function.
36 *
37 *******************************************************************************/
38 
_wcsicmp_l(wchar_t const * const lhs,wchar_t const * const rhs,_locale_t const plocinfo)39 extern "C" int __cdecl _wcsicmp_l (
40         wchar_t const * const lhs,
41         wchar_t const * const rhs,
42         _locale_t       const plocinfo
43         )
44 {
45     /* validation section */
46     _VALIDATE_RETURN(lhs != nullptr, EINVAL, _NLSCMPERROR);
47     _VALIDATE_RETURN(rhs != nullptr, EINVAL, _NLSCMPERROR);
48 
49     _LocaleUpdate _loc_update(plocinfo);
50 
51     // This check is still worth doing for wide but not narrow because
52     // we need to consult the UTF-16 ctype map for towlower operations.
53     if (_loc_update.GetLocaleT()->locinfo->locale_name[LC_CTYPE] == nullptr)
54     {
55         return __ascii_wcsicmp(lhs, rhs);
56     }
57 
58     unsigned short const * lhs_ptr = reinterpret_cast<unsigned short const *>(lhs);
59     unsigned short const * rhs_ptr = reinterpret_cast<unsigned short const *>(rhs);
60 
61     int result;
62     int lhs_value;
63     int rhs_value;
64     do
65     {
66         lhs_value = _towlower_internal(*lhs_ptr++, _loc_update.GetLocaleT());
67         rhs_value = _towlower_internal(*rhs_ptr++, _loc_update.GetLocaleT());
68         result = lhs_value - rhs_value;
69     }
70     while (result == 0 && lhs_value != 0);
71 
72     return result;
73 }
74 
__ascii_wcsicmp(wchar_t const * const lhs,wchar_t const * const rhs)75 extern "C" int __cdecl __ascii_wcsicmp(
76         wchar_t const * const lhs,
77         wchar_t const * const rhs
78         )
79 {
80     unsigned short const * lhs_ptr = reinterpret_cast<unsigned short const *>(lhs);
81     unsigned short const * rhs_ptr = reinterpret_cast<unsigned short const *>(rhs);
82 
83     int result;
84     int lhs_value;
85     int rhs_value;
86     do
87     {
88         lhs_value = __ascii_towlower(*lhs_ptr++);
89         rhs_value = __ascii_towlower(*rhs_ptr++);
90         result = lhs_value - rhs_value;
91     }
92     while (result == 0 && lhs_value != 0);
93 
94     return result;
95 }
96 
_wcsicmp(wchar_t const * const lhs,wchar_t const * const rhs)97 extern "C" int __cdecl _wcsicmp(
98         wchar_t const * const lhs,
99         wchar_t const * const rhs
100         )
101 {
102     if (!__acrt_locale_changed())
103     {
104         /* validation section */
105         _VALIDATE_RETURN(lhs != nullptr, EINVAL, _NLSCMPERROR);
106         _VALIDATE_RETURN(rhs != nullptr, EINVAL, _NLSCMPERROR);
107 
108         return __ascii_wcsicmp(lhs, rhs);
109     }
110 
111     return _wcsicmp_l(lhs, rhs, nullptr);
112 }
113