1// Licensed to the .NET Foundation under one or more agreements.
2// The .NET Foundation licenses this file to you under the MIT license.
3// See the LICENSE file in the project root for more information.
4
5/*++
6
7
8
9Module Name:
10
11 mbstring.c
12
13Abstract:
14
15 Implementation of the multi-byte string functions in the C runtime library that
16 are Windows specific.
17
18Implementation Notes:
19
20 Assuming it is not possible to change multi-byte code page using
21 the PAL (_setmbcp does not seem to be required), these functions
22 should have a trivial implementation (treat as single-byte). If it
23 is possible, then support for multi-byte code pages will have to
24 be implemented before these functions can behave correctly for
25 multi-byte strings.
26
27
28
29--*/
30
31#include "pal/palinternal.h"
32#include "pal/dbgmsg.h"
33
34#include <algorithm>
35
36SET_DEFAULT_DEBUG_CHANNEL(CRT);
37
38
39/*++
40Function:
41 _mbsinc
42
43Return Value
44
45Returns a pointer to the character that immediately follows string.
46
47Parameter
48
49string Character pointer
50
51Remarks
52
53The _mbsinc function returns a pointer to the first byte of the
54multibyte character that immediately follows string.
55
56--*/
57unsigned char *
58__cdecl
59_mbsinc(
60 const unsigned char *string)
61{
62 unsigned char *ret;
63
64 PERF_ENTRY(_mbsinc);
65 ENTRY("_mbsinc (string=%p)\n", string);
66
67 if (string == NULL)
68 {
69 ret = NULL;
70 }
71 else
72 {
73 ret = (unsigned char *) string;
74 if (IsDBCSLeadByteEx(CP_ACP, *ret))
75 {
76 ++ret;
77 }
78 ++ret;
79 }
80
81 LOGEXIT("_mbsinc returning unsigned char* %p (%s)\n", ret, ret);
82 PERF_EXIT(_mbsinc);
83 return ret;
84}
85
86
87/*++
88Function:
89 _mbsninc
90
91Return Value
92
93Returns a pointer to string after string has been incremented by count
94characters, or NULL if the supplied pointer is NULL. If count is
95greater than or equal to the number of characters in string, the
96result is undefined.
97
98Parameters
99
100string Source string
101count Number of characters to increment string pointer
102
103Remarks
104
105The _mbsninc function increments string by count multibyte
106characters. _mbsninc recognizes multibyte-character sequences
107according to the multibyte code page currently in use.
108
109--*/
110unsigned char *
111__cdecl
112_mbsninc(
113 const unsigned char *string, size_t count)
114{
115 unsigned char *ret;
116 CPINFO cpinfo;
117
118 PERF_ENTRY(_mbsninc);
119 ENTRY("_mbsninc (string=%p, count=%lu)\n", string, count);
120 if (string == NULL)
121 {
122 ret = NULL;
123 }
124 else
125 {
126 ret = (unsigned char *) string;
127 if (GetCPInfo(CP_ACP, &cpinfo) && cpinfo.MaxCharSize == 1)
128 {
129 ret += std::min(count, strlen((const char*)string));
130 }
131 else
132 {
133 while (count-- && (*ret != 0))
134 {
135 if (IsDBCSLeadByteEx(CP_ACP, *ret))
136 {
137 ++ret;
138 }
139 ++ret;
140 }
141 }
142 }
143 LOGEXIT("_mbsninc returning unsigned char* %p (%s)\n", ret, ret);
144 PERF_EXIT(_mbsninc);
145 return ret;
146}
147
148/*++
149Function:
150 _mbsdec
151
152Return Value
153
154_mbsdec returns a pointer to the character that immediately precedes
155current; _mbsdec returns NULL if the value of start is greater than or
156equal to that of current.
157
158Parameters
159
160start Pointer to first byte of any multibyte character in the source
161 string; start must precede current in the source string
162
163current Pointer to first byte of any multibyte character in the source
164 string; current must follow start in the source string
165
166--*/
167unsigned char *
168__cdecl
169_mbsdec(
170 const unsigned char *start,
171 const unsigned char *current)
172{
173 unsigned char *ret;
174 unsigned char *strPtr;
175 CPINFO cpinfo;
176
177 PERF_ENTRY(_mbsdec);
178 ENTRY("_mbsdec (start=%p, current=%p)\n", start, current);
179
180 if (current <= start)
181 {
182 ret = NULL;
183 }
184 else if (GetCPInfo(CP_ACP, &cpinfo) && cpinfo.MaxCharSize == 1)
185 {
186 ret = (unsigned char *) current - 1;
187 }
188 else
189 {
190 ret = strPtr = (unsigned char *) start;
191 while (strPtr < current)
192 {
193 ret = strPtr;
194 if (IsDBCSLeadByteEx(CP_ACP, *strPtr))
195 {
196 ++strPtr;
197 }
198 ++strPtr;
199 }
200 }
201 LOGEXIT("_mbsdec returning unsigned int %p (%s)\n", ret, ret);
202 PERF_EXIT(_mbsdec);
203 return ret;
204}
205