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