source: trunk/src/kernel32/unicode/string.c@ 8666

Last change on this file since 8666 was 8666, checked in by sandervl, 23 years ago

added strtolW & strtoulW

File size: 5.9 KB
Line 
1/*
2 * Unicode string manipulation functions
3 *
4 * Copyright 2000 Alexandre Julliard
5 */
6
7#include <windows.h>
8#include <limits.h>
9
10#include "wine/unicode.h"
11
12int strcmpiW( const WCHAR *str1, const WCHAR *str2 )
13{
14 for (;;)
15 {
16 int ret = toupperW(*str1) - toupperW(*str2);
17 if (ret || !*str1) return ret;
18 str1++;
19 str2++;
20 }
21}
22
23int strncmpiW( const WCHAR *str1, const WCHAR *str2, int n )
24{
25 int ret = 0;
26 for ( ; n > 0; n--, str1++, str2++)
27 if ((ret = toupperW(*str1) - toupperW(*str2)) || !*str1) break;
28 return ret;
29}
30
31WCHAR *strstrW( const WCHAR *str, const WCHAR *sub )
32{
33 while (*str)
34 {
35 const WCHAR *p1 = str, *p2 = sub;
36 while (*p1 && *p2 && *p1 == *p2) { p1++; p2++; }
37 if (!*p2) return (WCHAR *)str;
38 str++;
39 }
40 return NULL;
41}
42
43/* strtolW and strtoulW implementation based on the GNU C library code */
44/* Copyright (C) 1991,92,94,95,96,97,98,99,2000,2001 Free Software Foundation, Inc. */
45
46long int strtolW( const WCHAR *nptr, WCHAR **endptr, int base )
47{
48 int negative;
49 register unsigned long int cutoff;
50 register unsigned int cutlim;
51 register unsigned long int i;
52 register const WCHAR *s;
53 register WCHAR c;
54 const WCHAR *save, *end;
55 int overflow;
56
57 if (base < 0 || base == 1 || base > 36) return 0;
58
59 save = s = nptr;
60
61 /* Skip white space. */
62 while (isspaceW (*s))
63 ++s;
64 if (!*s) goto noconv;
65
66 /* Check for a sign. */
67 negative = 0;
68 if (*s == '-')
69 {
70 negative = 1;
71 ++s;
72 }
73 else if (*s == '+')
74 ++s;
75
76 /* Recognize number prefix and if BASE is zero, figure it out ourselves. */
77 if (*s == '0')
78 {
79 if ((base == 0 || base == 16) && toupperW(s[1]) == 'X')
80 {
81 s += 2;
82 base = 16;
83 }
84 else if (base == 0)
85 base = 8;
86 }
87 else if (base == 0)
88 base = 10;
89
90 /* Save the pointer so we can check later if anything happened. */
91 save = s;
92 end = NULL;
93
94 cutoff = ULONG_MAX / (unsigned long int) base;
95 cutlim = ULONG_MAX % (unsigned long int) base;
96
97 overflow = 0;
98 i = 0;
99 c = *s;
100 for (;c != '\0'; c = *++s)
101 {
102 if (s == end)
103 break;
104 if (c >= '0' && c <= '9')
105 c -= '0';
106 else if (isalphaW (c))
107 c = toupperW (c) - 'A' + 10;
108 else
109 break;
110 if ((int) c >= base)
111 break;
112 /* Check for overflow. */
113 if (i > cutoff || (i == cutoff && c > cutlim))
114 overflow = 1;
115 else
116 {
117 i *= (unsigned long int) base;
118 i += c;
119 }
120 }
121
122 /* Check if anything actually happened. */
123 if (s == save)
124 goto noconv;
125
126 /* Store in ENDPTR the address of one character
127 past the last character we converted. */
128 if (endptr != NULL)
129 *endptr = (WCHAR *)s;
130
131 /* Check for a value that is within the range of
132 `unsigned LONG int', but outside the range of `LONG int'. */
133 if (overflow == 0
134 && i > (negative
135 ? -((unsigned long int) (LONG_MIN + 1)) + 1
136 : (unsigned long int) LONG_MAX))
137 overflow = 1;
138
139 if (overflow)
140 {
141 return negative ? LONG_MIN : LONG_MAX;
142 }
143
144 /* Return the result of the appropriate sign. */
145 return negative ? -i : i;
146
147noconv:
148 /* We must handle a special case here: the base is 0 or 16 and the
149 first two characters are '0' and 'x', but the rest are no
150 hexadecimal digits. This is no error case. We return 0 and
151 ENDPTR points to the `x`. */
152 if (endptr != NULL)
153 {
154 if (save - nptr >= 2 && toupperW (save[-1]) == 'X'
155 && save[-2] == '0')
156 *endptr = (WCHAR *)&save[-1];
157 else
158 /* There was no number to convert. */
159 *endptr = (WCHAR *)nptr;
160 }
161
162 return 0L;
163}
164
165unsigned long int strtoulW( const WCHAR *nptr, WCHAR **endptr, int base )
166{
167 int negative;
168 register unsigned long int cutoff;
169 register unsigned int cutlim;
170 register unsigned long int i;
171 register const WCHAR *s;
172 register WCHAR c;
173 const WCHAR *save, *end;
174 int overflow;
175
176 if (base < 0 || base == 1 || base > 36) return 0;
177
178 save = s = nptr;
179
180 /* Skip white space. */
181 while (isspaceW (*s))
182 ++s;
183 if (!*s) goto noconv;
184
185 /* Check for a sign. */
186 negative = 0;
187 if (*s == '-')
188 {
189 negative = 1;
190 ++s;
191 }
192 else if (*s == '+')
193 ++s;
194
195 /* Recognize number prefix and if BASE is zero, figure it out ourselves. */
196 if (*s == '0')
197 {
198 if ((base == 0 || base == 16) && toupperW(s[1]) == 'X')
199 {
200 s += 2;
201 base = 16;
202 }
203 else if (base == 0)
204 base = 8;
205 }
206 else if (base == 0)
207 base = 10;
208
209 /* Save the pointer so we can check later if anything happened. */
210 save = s;
211 end = NULL;
212
213 cutoff = ULONG_MAX / (unsigned long int) base;
214 cutlim = ULONG_MAX % (unsigned long int) base;
215
216 overflow = 0;
217 i = 0;
218 c = *s;
219 for (;c != '\0'; c = *++s)
220 {
221 if (s == end)
222 break;
223 if (c >= '0' && c <= '9')
224 c -= '0';
225 else if (isalphaW (c))
226 c = toupperW (c) - 'A' + 10;
227 else
228 break;
229 if ((int) c >= base)
230 break;
231 /* Check for overflow. */
232 if (i > cutoff || (i == cutoff && c > cutlim))
233 overflow = 1;
234 else
235 {
236 i *= (unsigned long int) base;
237 i += c;
238 }
239 }
240
241 /* Check if anything actually happened. */
242 if (s == save)
243 goto noconv;
244
245 /* Store in ENDPTR the address of one character
246 past the last character we converted. */
247 if (endptr != NULL)
248 *endptr = (WCHAR *)s;
249
250 if (overflow)
251 {
252 return ULONG_MAX;
253 }
254
255 /* Return the result of the appropriate sign. */
256 return negative ? -i : i;
257
258noconv:
259 /* We must handle a special case here: the base is 0 or 16 and the
260 first two characters are '0' and 'x', but the rest are no
261 hexadecimal digits. This is no error case. We return 0 and
262 ENDPTR points to the `x`. */
263 if (endptr != NULL)
264 {
265 if (save - nptr >= 2 && toupperW (save[-1]) == 'X'
266 && save[-2] == '0')
267 *endptr = (WCHAR *)&save[-1];
268 else
269 /* There was no number to convert. */
270 *endptr = (WCHAR *)nptr;
271 }
272
273 return 0L;
274}
Note: See TracBrowser for help on using the repository browser.