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 | |
9 | Module Name: |
10 | |
11 | mbstring.c |
12 | |
13 | Abstract: |
14 | |
15 | Implementation of the multi-byte string functions in the C runtime library that |
16 | are Windows specific. |
17 | |
18 | Implementation 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 | |
36 | SET_DEFAULT_DEBUG_CHANNEL(CRT); |
37 | |
38 | |
39 | /*++ |
40 | Function: |
41 | _mbsinc |
42 | |
43 | Return Value |
44 | |
45 | Returns a pointer to the character that immediately follows string. |
46 | |
47 | Parameter |
48 | |
49 | string Character pointer |
50 | |
51 | Remarks |
52 | |
53 | The _mbsinc function returns a pointer to the first byte of the |
54 | multibyte character that immediately follows string. |
55 | |
56 | --*/ |
57 | unsigned 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 | /*++ |
88 | Function: |
89 | _mbsninc |
90 | |
91 | Return Value |
92 | |
93 | Returns a pointer to string after string has been incremented by count |
94 | characters, or NULL if the supplied pointer is NULL. If count is |
95 | greater than or equal to the number of characters in string, the |
96 | result is undefined. |
97 | |
98 | Parameters |
99 | |
100 | string Source string |
101 | count Number of characters to increment string pointer |
102 | |
103 | Remarks |
104 | |
105 | The _mbsninc function increments string by count multibyte |
106 | characters. _mbsninc recognizes multibyte-character sequences |
107 | according to the multibyte code page currently in use. |
108 | |
109 | --*/ |
110 | unsigned 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 | /*++ |
149 | Function: |
150 | _mbsdec |
151 | |
152 | Return Value |
153 | |
154 | _mbsdec returns a pointer to the character that immediately precedes |
155 | current; _mbsdec returns NULL if the value of start is greater than or |
156 | equal to that of current. |
157 | |
158 | Parameters |
159 | |
160 | start Pointer to first byte of any multibyte character in the source |
161 | string; start must precede current in the source string |
162 | |
163 | current Pointer to first byte of any multibyte character in the source |
164 | string; current must follow start in the source string |
165 | |
166 | --*/ |
167 | unsigned 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 | |