xref: /reactos/sdk/lib/ucrt/string/wcsnicmp.cpp (revision 53d808d2)
1 /***
2 *wcsnicmp.cpp - compare n chars of wide-character strings, ignoring case
3 *
4 *       Copyright (c) Microsoft Corporation. All rights reserved.
5 *
6 *Purpose:
7 *       defines _wcsnicmp() - Compares at most n characters of two wchar_t
8 *       strings, without regard to case.
9 *
10 *******************************************************************************/
11 #include <corecrt_internal.h>
12 #include <ctype.h>
13 #include <corecrt_internal_securecrt.h>
14 #include <locale.h>
15 #include <string.h>
16 
17 /***
18 *int _wcsnicmp(lhs, rhs, count) - compares count wchar_t of strings,
19 *       ignore case
20 *
21 *Purpose:
22 *       Compare the two strings for ordinal order.  Stops the comparison
23 *       when the following occurs: (1) strings differ, (2) the end of the
24 *       strings is reached, or (3) count characters have been compared.
25 *       For the purposes of the comparison, upper case characters are
26 *       converted to lower case (wide-characters).
27 *
28 *Entry:
29 *       wchar_t *lhs, *rhs - strings to compare
30 *       size_t count - maximum number of characters to compare
31 *
32 *Exit:
33 *       Returns -1 if lhs < rhs
34 *       Returns 0 if lhs == rhs
35 *       Returns 1 if lhs > rhs
36 *       Returns _NLSCMPERROR if something went wrong
37 *       This range of return values may differ from other *cmp/*coll functions.
38 *
39 *Exceptions:
40 *       Input parameters are validated. Refer to the validation section of the function.
41 *
42 *******************************************************************************/
43 
44 extern "C" int __cdecl _wcsnicmp_l (
45         wchar_t const * const lhs,
46         wchar_t const * const rhs,
47         size_t          const count,
48         _locale_t       const plocinfo
49         )
50 {
51     /* validation section */
52     _VALIDATE_RETURN(lhs != nullptr, EINVAL, _NLSCMPERROR);
53     _VALIDATE_RETURN(rhs != nullptr, EINVAL, _NLSCMPERROR);
54 
55     if (count == 0)
56     {
57         return 0;
58     }
59 
60     _LocaleUpdate _loc_update(plocinfo);
61 
62     // This check is still worth doing for wide but not narrow because
63     // we need to consult the UTF-16 ctype map for towlower operations.
64     if (_loc_update.GetLocaleT()->locinfo->locale_name[LC_CTYPE] == nullptr)
65     {
66         return __ascii_wcsnicmp(lhs, rhs, count);
67     }
68 
69     unsigned short const * lhs_ptr = reinterpret_cast<unsigned short const *>(lhs);
70     unsigned short const * rhs_ptr = reinterpret_cast<unsigned short const *>(rhs);
71 
72     int result;
73     int lhs_value;
74     int rhs_value;
75     size_t remaining = count;
76     do
77     {
78         lhs_value = _towlower_internal(*lhs_ptr++, _loc_update.GetLocaleT());
79         rhs_value = _towlower_internal(*rhs_ptr++, _loc_update.GetLocaleT());
80         result = lhs_value - rhs_value;
81     }
82     while (result == 0 && lhs_value != 0 && --remaining != 0);
83 
84     return result;
85 }
86 
87 extern "C" int __cdecl __ascii_wcsnicmp(
88         wchar_t const * const lhs,
89         wchar_t const * const rhs,
90         size_t          const count
91         )
92 {
93     if (count == 0)
94     {
95         return 0;
96     }
97 
98     unsigned short const * lhs_ptr = reinterpret_cast<unsigned short const *>(lhs);
99     unsigned short const * rhs_ptr = reinterpret_cast<unsigned short const *>(rhs);
100 
101     int result;
102     int lhs_value;
103     int rhs_value;
104     size_t remaining = count;
105     do
106     {
107         lhs_value = __ascii_towlower(*lhs_ptr++);
108         rhs_value = __ascii_towlower(*rhs_ptr++);
109         result = lhs_value - rhs_value;
110     }
111     while (result == 0 && lhs_value != 0 && --remaining != 0);
112 
113     return result;
114 }
115 
116 extern "C" int __cdecl _wcsnicmp (
117         wchar_t const * const lhs,
118         wchar_t const * const rhs,
119         size_t          const count
120         )
121 {
122     if (!__acrt_locale_changed())
123     {
124         /* validation section */
125         _VALIDATE_RETURN(lhs != nullptr, EINVAL, _NLSCMPERROR);
126         _VALIDATE_RETURN(rhs != nullptr, EINVAL, _NLSCMPERROR);
127 
128         return __ascii_wcsnicmp(lhs, rhs, count);
129     }
130 
131     return _wcsnicmp_l(lhs, rhs, count, nullptr);
132 }
133