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