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