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