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