1 /*** 2 *strlwr.c - routine to map upper-case characters in a string to lower-case 3 * 4 * Copyright (c) Microsoft Corporation. All rights reserved. 5 * 6 *Purpose: 7 * Converts all the upper case characters in a string to lower case, 8 * in place. 9 * 10 *******************************************************************************/ 11 #include <corecrt_internal.h> 12 #include <ctype.h> 13 #include <corecrt_internal_securecrt.h> 14 #include <limits.h> 15 #include <locale.h> 16 #include <string.h> 17 18 #pragma warning(disable:__WARNING_POTENTIAL_BUFFER_OVERFLOW_NULLTERMINATED) // 26018 19 20 /*** 21 *char *_strlwr(string) - map upper-case characters in a string to lower-case 22 * 23 *Purpose: 24 * _strlwr() converts upper-case characters in a null-terminated string 25 * to their lower-case equivalents. Conversion is done in place and 26 * characters other than upper-case letters are not modified. 27 * 28 * In the C locale, this function modifies only 7-bit ASCII characters 29 * in the range 0x41 through 0x5A ('A' through 'Z'). 30 * 31 * If the locale is not the 'C' locale, LCMapString() is used to do 32 * the work. Assumes enough space in the string to hold result. 33 * 34 *Entry: 35 * char *string - string to change to lower case 36 * 37 *Exit: 38 * input string address 39 * 40 *Exceptions: 41 * The original string is returned unchanged on any error, and errno is set. 42 * 43 *******************************************************************************/ 44 45 extern "C" char * __cdecl _strlwr_l ( 46 char * string, 47 _locale_t plocinfo 48 ) 49 { 50 _strlwr_s_l(string, (size_t)(-1), plocinfo); 51 return string; 52 } 53 54 extern "C" char * __cdecl _strlwr ( 55 char * string 56 ) 57 { 58 if (!__acrt_locale_changed()) 59 { 60 char * cp; 61 62 /* validation section */ 63 _VALIDATE_RETURN(string != nullptr, EINVAL, nullptr); 64 65 for (cp=string; *cp; ++cp) 66 { 67 if ('A' <= *cp && *cp <= 'Z') 68 *cp += 'a' - 'A'; 69 } 70 71 return(string); 72 } 73 else 74 { 75 _strlwr_s_l(string, (size_t)(-1), nullptr); 76 return string; 77 } 78 } 79 80 /*** 81 *errno_t _strlwr_s(string, size_t) - map upper-case characters in a string to lower-case 82 * 83 *Purpose: 84 * _strlwr_s() converts upper-case characters in a null-terminated string 85 * to their lower-case equivalents. Conversion is done in place and 86 * characters other than upper-case letters are not modified. 87 * 88 * In the C locale, this function modifies only 7-bit ASCII characters 89 * in the range 0x41 through 0x5A ('A' through 'Z'). 90 * 91 * If the locale is not the 'C' locale, LCMapString() is used to do 92 * the work. Assumes enough space in the string to hold result. 93 * 94 *Entry: 95 * char *string - string to change to lower case 96 * size_t sizeInBytes - size of the destination buffer 97 * 98 *Exit: 99 * the error code 100 * 101 *Exceptions: 102 * The original string is returned unchanged on any error, and errno is set. 103 * 104 *******************************************************************************/ 105 106 static 107 errno_t __cdecl _strlwr_s_l_stat ( 108 _Inout_updates_z_(sizeInBytes) char * const string, 109 size_t const sizeInBytes, 110 _locale_t const plocinfo 111 ) throw() 112 { 113 114 int dstsize; /* size of dst string buffer (include null) */ 115 size_t stringlen; 116 117 /* validation section */ 118 _VALIDATE_RETURN_ERRCODE(string != nullptr, EINVAL); 119 stringlen = strnlen(string, sizeInBytes); 120 if (stringlen >= sizeInBytes) 121 { 122 _RESET_STRING(string, sizeInBytes); 123 _RETURN_DEST_NOT_NULL_TERMINATED(string, sizeInBytes); 124 } 125 _FILL_STRING(string, sizeInBytes, stringlen + 1); 126 127 if ( plocinfo->locinfo->locale_name[LC_CTYPE] == nullptr ) { 128 char *cp; /* traverses string for C locale conversion */ 129 130 for ( cp = string ; *cp ; ++cp ) 131 if ( ('A' <= *cp) && (*cp <= 'Z') ) 132 *cp -= 'A' - 'a'; 133 134 return 0; 135 } /* C locale */ 136 137 /* Inquire size of dst string */ 138 if ( 0 == (dstsize = __acrt_LCMapStringA( 139 plocinfo, 140 plocinfo->locinfo->locale_name[LC_CTYPE], 141 LCMAP_LOWERCASE, 142 string, 143 -1, 144 nullptr, 145 0, 146 plocinfo->locinfo->_public._locale_lc_codepage, 147 TRUE )) ) 148 { 149 errno = EILSEQ; 150 return errno; 151 } 152 153 if (sizeInBytes < (size_t)dstsize) 154 { 155 _RESET_STRING(string, sizeInBytes); 156 _RETURN_BUFFER_TOO_SMALL(string, sizeInBytes); 157 } 158 159 /* Allocate space for dst */ 160 __crt_scoped_stack_ptr<char> dst(_malloca_crt_t(char, dstsize)); 161 if (!dst) 162 { 163 errno = ENOMEM; 164 return errno; 165 } 166 167 /* Map src string to dst string in alternate case */ 168 if (__acrt_LCMapStringA( 169 plocinfo, 170 plocinfo->locinfo->locale_name[LC_CTYPE], 171 LCMAP_LOWERCASE, 172 string, 173 -1, 174 dst.get(), 175 dstsize, 176 plocinfo->locinfo->_public._locale_lc_codepage, 177 TRUE ) != 0) 178 { 179 /* copy dst string to return string */ 180 return strcpy_s(string, sizeInBytes, dst.get()); 181 } 182 else 183 { 184 return errno = EILSEQ; 185 } 186 } 187 188 extern "C" errno_t __cdecl _strlwr_s_l ( 189 char * string, 190 size_t sizeInBytes, 191 _locale_t plocinfo 192 ) 193 { 194 195 _LocaleUpdate _loc_update(plocinfo); 196 197 return _strlwr_s_l_stat(string, sizeInBytes, _loc_update.GetLocaleT()); 198 } 199 200 extern "C" errno_t __cdecl _strlwr_s( 201 char * string, 202 size_t sizeInBytes 203 ) 204 { 205 return _strlwr_s_l(string, sizeInBytes, nullptr); 206 } 207