xref: /reactos/sdk/lib/ucrt/string/memicmp.cpp (revision a6a07059)
1 /***
2 *memicmp.cpp - compare memory, ignore case
3 *
4 *       Copyright (c) Microsoft Corporation. All rights reserved.
5 *
6 *Purpose:
7 *       defines _memicmp() - compare two blocks of memory for ordinal
8 *       order.  Case is ignored in the comparison.
9 *
10 *******************************************************************************/
11 #include <corecrt_internal.h>
12 #include <ctype.h>
13 #include <locale.h>
14 #include <string.h>
15 
16 /***
17 *int _memicmp(lhs, rhs, count) - compare two blocks of memory, ignore case
18 *
19 *Purpose:
20 *       Compares count bytes of the two blocks of memory stored at lhs
21 *       and rhs.  The characters are converted to lowercase before
22 *       comparing (not permanently), so case is ignored in the search.
23 *
24 *Entry:
25 *       char *lhs, *rhs - memory buffers to compare
26 *       size_t count - maximum length to compare
27 *
28 *Exit:
29 *       Returns < 0 if lhs < rhs
30 *       Returns 0 if lhs == rhs
31 *       Returns > 0 if lhs > rhs
32 *       Returns _NLSCMPERROR if something went wrong
33 *
34 *Uses:
35 *
36 *Exceptions:
37 *       Input parameters are validated. Refer to the validation section of the function.
38 *
39 *******************************************************************************/
40 
41 extern "C" int __cdecl _memicmp_l (
42         void const * const lhs,
43         void const * const rhs,
44         size_t       const count,
45         _locale_t    const plocinfo
46         )
47 {
48     /* validation section */
49     _VALIDATE_RETURN(lhs != nullptr || count == 0, EINVAL, _NLSCMPERROR);
50     _VALIDATE_RETURN(rhs != nullptr || count == 0, EINVAL, _NLSCMPERROR);
51 
52     if (count == 0)
53     {
54         return 0;
55     }
56 
57     unsigned char const * lhs_ptr = static_cast<unsigned char const *>(lhs);
58     unsigned char const * rhs_ptr = static_cast<unsigned char const *>(rhs);
59 
60     _LocaleUpdate _loc_update(plocinfo);
61 
62     int result;
63     size_t remaining = count;
64     do
65     {
66         result = _tolower_fast_internal(*lhs_ptr++, _loc_update.GetLocaleT())
67             - _tolower_fast_internal(*rhs_ptr++, _loc_update.GetLocaleT());
68     }
69     while (result == 0 && --remaining != 0);
70 
71     return result;
72 }
73 
74 
75 #if !defined(_M_IX86) || defined(_M_HYBRID_X86_ARM64)
76 
77 extern "C" int __cdecl __ascii_memicmp (
78         void const * const lhs,
79         void const * const rhs,
80         size_t       const count
81         )
82 {
83     if (count == 0)
84     {
85         return 0;
86     }
87 
88     unsigned char const * lhs_ptr = static_cast<unsigned char const *>(lhs);
89     unsigned char const * rhs_ptr = static_cast<unsigned char const *>(rhs);
90 
91     int result;
92     size_t remaining = count;
93     do
94     {
95         result = __ascii_tolower(*lhs_ptr++) - __ascii_tolower(*rhs_ptr++);
96     }
97     while (result == 0 && --remaining != 0);
98 
99     return result;
100 }
101 
102 #endif  /* !_M_IX86 || _M_HYBRID_X86_ARM64 */
103 
104 extern "C" int __cdecl _memicmp (
105         void const * const lhs,
106         void const * const rhs,
107         size_t       const count
108         )
109 {
110     if (!__acrt_locale_changed())
111     {
112         /* validation section */
113         _VALIDATE_RETURN(lhs != nullptr || count == 0, EINVAL, _NLSCMPERROR);
114         _VALIDATE_RETURN(rhs != nullptr || count == 0, EINVAL, _NLSCMPERROR);
115 
116         return __ascii_memicmp(lhs, rhs, count);
117     }
118 
119     return _memicmp_l(lhs, rhs, count, nullptr);
120 }
121