xref: /reactos/sdk/lib/ucrt/mbstring/mbsrev.cpp (revision 04e0dc4a)
1 /***
2 *mbsrev.c - Reverse a string in place (MBCS)
3 *
4 *       Copyright (c) Microsoft Corporation.  All rights reserved.
5 *
6 *Purpose:
7 *       Reverse a string in place (MBCS)
8 *
9 *******************************************************************************/
10 #ifndef _MBCS
11     #error This file should only be compiled with _MBCS defined
12 #endif
13 
14 #include <corecrt_internal_mbstring.h>
15 #include <locale.h>
16 #include <string.h>
17 
18 
19 /***
20 * _mbsrev - Reverse a string in place (MBCS)
21 *
22 *Purpose:
23 *       Reverses the order of characters in the string.  The terminating
24 *       null character remains in place.  The order of MBCS characters
25 *       is not changed.
26 *
27 *Entry:
28 *       unsigned char *string = string to reverse
29 *
30 *Exit:
31 *       returns string - now with reversed characters
32 *
33 *Exceptions:
34 *       Input parameters are validated. Refer to the validation section of the function.
35 *
36 *******************************************************************************/
37 
_mbsrev_l(unsigned char * string,_locale_t plocinfo)38 extern "C" unsigned char * __cdecl _mbsrev_l(
39         unsigned char *string,
40         _locale_t plocinfo
41         )
42 {
43         unsigned char *start = string;
44         unsigned char *left  = string;
45         unsigned char c;
46         _LocaleUpdate _loc_update(plocinfo);
47 
48         /* validation section */
49         _VALIDATE_RETURN(string != nullptr, EINVAL, nullptr);
50 
51         if (_loc_update.GetLocaleT()->mbcinfo->ismbcodepage == 0)
52             return (unsigned char *)_strrev((char *)string);
53 
54 
55         /* first go through and reverse the bytes in MBCS chars */
56         while ( *string ) {
57             if ( _ismbblead_l(*string++, _loc_update.GetLocaleT()) ) {
58                 if ( *string ) {
59                     c = *string;
60                     *string = *(string - 1);
61                     *(string - 1) = c;
62                     string++;
63                 }
64                 else
65                 {
66                     /*  second byte is EOS
67                         There is nothing really satisfying to do here. We have a string
68                         that ends in leadbyte,'\0'. Reversing this would lead to the leadbyte
69                         becoming falsely attached to the character before it:
70                         (XL0 -> LX0, X has suddenly become a trailbyte)
71 
72                         So what we choose to do is assert and purge the dud byte from within the
73                         string.
74                     */
75                     errno = EINVAL;
76                     _ASSERTE(("Bad MBCS string passed into _mbsrev",0));
77 
78                     /* String has at least moved once already, so this is safe */
79                     _ASSERTE(string>start);
80 
81                     /* move back one to point at the dud leadbyte */
82                     --string;
83 
84                     /* now truncate the string one byte earlier */
85                     *string='\0';
86 
87                     break;
88                 }
89             }
90         }
91 
92         /* now reverse the whole string */
93         string--;
94         while ( left < string ) {
95             c = *left;
96             *left++ = *string;
97             *string-- = c;
98         }
99 
100         return ( start );
101 }
102 
103 extern "C" unsigned char * (__cdecl _mbsrev)(
104         unsigned char *string
105         )
106 {
107     return _mbsrev_l(string, nullptr);
108 }
109