xref: /reactos/sdk/lib/ucrt/string/wcslwr.cpp (revision fe93a3f9)
1 /***
2 *wcslwr.c - routine to map upper-case characters in a wchar_t string
3 *       to lower-case
4 *
5 *       Copyright (c) Microsoft Corporation. All rights reserved.
6 *
7 *Purpose:
8 *       Converts all the upper case characters in a wchar_t string
9 *       to lower case, in place.
10 *
11 *******************************************************************************/
12 #include <corecrt_internal.h>
13 #include <ctype.h>
14 #include <corecrt_internal_securecrt.h>
15 #include <locale.h>
16 #include <string.h>
17 
18 #pragma warning(disable:__WARNING_POTENTIAL_BUFFER_OVERFLOW_NULLTERMINATED) // 26018
19 
20 /***
21 *wchar_t *_wcslwr(string) - map upper-case characters in a string to lower-case
22 *
23 *Purpose:
24 *       wcslwr converts upper-case characters in a null-terminated wchar_t
25 *       string to their lower-case equivalents.  The result may be longer or
26 *       shorter than the original string.  Assumes enough space in string
27 *       to hold the result.
28 *
29 *Entry:
30 *       wchar_t *wsrc - wchar_t string to change to lower case
31 *
32 *Exit:
33 *       input string address
34 *
35 *Exceptions:
36 *       on an error, the original string is unaltered, and errno is set
37 *
38 *******************************************************************************/
39 
40 extern "C" wchar_t * __cdecl _wcslwr_l (
41         wchar_t * wsrc,
42         _locale_t plocinfo
43         )
44 {
45     _wcslwr_s_l(wsrc, (size_t)(-1), plocinfo);
46     return wsrc;
47 }
48 
49 extern "C" wchar_t * __cdecl _wcslwr (
50         wchar_t * wsrc
51         )
52 {
53     if (!__acrt_locale_changed())
54     {
55         wchar_t * p;
56 
57         /* validation section */
58         _VALIDATE_RETURN(wsrc != nullptr, EINVAL, nullptr);
59 
60         for (p=wsrc; *p; ++p)
61         {
62             if (L'A' <= *p && *p <= L'Z')
63                 *p += (wchar_t)L'a' - (wchar_t)L'A';
64         }
65     } else {
66         _wcslwr_s_l(wsrc, (size_t)(-1), nullptr);
67         return wsrc;
68     }
69 
70     return(wsrc);
71 }
72 
73 /***
74 *errno_t _wcslwr_s(string, size_t) - map upper-case characters in a string to lower-case
75 *
76 *Purpose:
77 *       wcslwr_s converts upper-case characters in a null-terminated wchar_t
78 *       string to their lower-case equivalents.  The result may be longer or
79 *       shorter than the original string.
80 *
81 *Entry:
82 *       wchar_t *wsrc - wchar_t string to change to lower case
83 *       size_t sizeInWords - size of the destination buffer
84 *
85 *Exit:
86 *       the error code
87 *
88 *Exceptions:
89 *       on an error, the original string is unaltered, and errno is set
90 *
91 *******************************************************************************/
92 
93 static errno_t __cdecl _wcslwr_s_l_stat (
94         _Inout_updates_z_(sizeInWords) wchar_t * wsrc,
95         size_t sizeInWords,
96         _locale_t plocinfo
97         )
98 {
99 
100     wchar_t *p;             /* traverses string for C locale conversion */
101     int dstsize;            /* size in wide chars of wdst string buffer (include null) */
102     size_t stringlen;
103 
104     /* validation section */
105     _VALIDATE_RETURN_ERRCODE(wsrc != nullptr, EINVAL);
106     stringlen = wcsnlen(wsrc, sizeInWords);
107     if (stringlen >= sizeInWords)
108     {
109         _RESET_STRING(wsrc, sizeInWords);
110         _RETURN_DEST_NOT_NULL_TERMINATED(wsrc, sizeInWords);
111     }
112     _FILL_STRING(wsrc, sizeInWords, stringlen + 1);
113 
114     if ( plocinfo->locinfo->locale_name[LC_CTYPE] == nullptr)
115     {
116         for ( p = wsrc ; *p ; p++ )
117         {
118             if ( (*p >= (wchar_t)L'A') && (*p <= (wchar_t)L'Z') )
119             {
120                 *p -= static_cast<wchar_t>(L'A' - L'a');
121             }
122         }
123 
124         return 0;
125     }   /* C locale */
126 
127     /* Inquire size of wdst string */
128     if ( (dstsize = __acrt_LCMapStringW(
129                     plocinfo->locinfo->locale_name[LC_CTYPE],
130                     LCMAP_LOWERCASE,
131                     wsrc,
132                     -1,
133                     nullptr,
134                     0
135                     )) == 0 )
136     {
137         errno = EILSEQ;
138         return errno;
139     }
140 
141     if (sizeInWords < (size_t)dstsize)
142     {
143         _RESET_STRING(wsrc, sizeInWords);
144         _RETURN_BUFFER_TOO_SMALL(wsrc, sizeInWords);
145     }
146 
147     /* Allocate space for wdst */
148     __crt_scoped_stack_ptr<wchar_t> const wdst(_malloca_crt_t(wchar_t, dstsize));
149     if (!wdst)
150     {
151         errno = ENOMEM;
152         return errno;
153     }
154 
155     /* Map wrc string to wide-character wdst string in alternate case */
156     if (__acrt_LCMapStringW(
157                 plocinfo->locinfo->locale_name[LC_CTYPE],
158                 LCMAP_LOWERCASE,
159                 wsrc,
160                 -1,
161                 wdst.get(),
162                 dstsize
163                 ) != 0)
164     {
165         /* Copy wdst string to user string */
166         return wcscpy_s(wsrc, sizeInWords, wdst.get());
167     }
168     else
169     {
170         return errno = EILSEQ;
171     }
172 }
173 
174 extern "C" errno_t __cdecl _wcslwr_s_l (
175         wchar_t * wsrc,
176         size_t sizeInWords,
177         _locale_t plocinfo
178         )
179 {
180     _LocaleUpdate _loc_update(plocinfo);
181 
182     return _wcslwr_s_l_stat(wsrc, sizeInWords, _loc_update.GetLocaleT());
183 }
184 
185 
186 extern "C" errno_t __cdecl _wcslwr_s (
187         wchar_t * wsrc,
188         size_t sizeInWords
189         )
190 {
191     return _wcslwr_s_l(wsrc, sizeInWords, nullptr);
192 }
193