xref: /reactos/sdk/lib/ucrt/string/strlwr.cpp (revision 53d808d2)
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