VirtualBox

source: vbox/trunk/src/VBox/Additions/WINNT/Graphics/Wine/libWine/string.c@ 19982

Last change on this file since 19982 was 19678, checked in by vboxsync, 16 years ago

opengl: update wine to 1.1.21, add d3d9.dll to build list

  • Property svn:eol-style set to native
File size: 13.5 KB
Line 
1/*
2 * Unicode string manipulation functions
3 *
4 * Copyright 2000 Alexandre Julliard
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 */
20
21/*
22 * Sun LGPL Disclaimer: For the avoidance of doubt, except that if any license choice
23 * other than GPL or LGPL is available it will apply instead, Sun elects to use only
24 * the Lesser General Public License version 2.1 (LGPLv2) at this time for any software where
25 * a choice of LGPL license versions is made available with the language indicating
26 * that LGPLv2 or any later version may be used, or where a choice of which version
27 * of the LGPL is applied is otherwise unspecified.
28 */
29
30#include <assert.h>
31#include <limits.h>
32#include <stdio.h>
33
34#define WINE_UNICODE_INLINE /* nothing */
35#include "wine/unicode.h"
36
37int strcmpiW( const WCHAR *str1, const WCHAR *str2 )
38{
39 for (;;)
40 {
41 int ret = tolowerW(*str1) - tolowerW(*str2);
42 if (ret || !*str1) return ret;
43 str1++;
44 str2++;
45 }
46}
47
48int strncmpiW( const WCHAR *str1, const WCHAR *str2, int n )
49{
50 int ret = 0;
51 for ( ; n > 0; n--, str1++, str2++)
52 if ((ret = tolowerW(*str1) - tolowerW(*str2)) || !*str1) break;
53 return ret;
54}
55
56int memicmpW( const WCHAR *str1, const WCHAR *str2, int n )
57{
58 int ret = 0;
59 for ( ; n > 0; n--, str1++, str2++)
60 if ((ret = tolowerW(*str1) - tolowerW(*str2))) break;
61 return ret;
62}
63
64WCHAR *strstrW( const WCHAR *str, const WCHAR *sub )
65{
66 while (*str)
67 {
68 const WCHAR *p1 = str, *p2 = sub;
69 while (*p1 && *p2 && *p1 == *p2) { p1++; p2++; }
70 if (!*p2) return (WCHAR *)str;
71 str++;
72 }
73 return NULL;
74}
75
76/* strtolW and strtoulW implementation based on the GNU C library code */
77/* Copyright (C) 1991,92,94,95,96,97,98,99,2000,2001 Free Software Foundation, Inc. */
78
79long int strtolW( const WCHAR *nptr, WCHAR **endptr, int base )
80{
81 int negative;
82 register unsigned long int cutoff;
83 register unsigned int cutlim;
84 register unsigned long int i;
85 register const WCHAR *s;
86 register WCHAR c;
87 const WCHAR *save, *end;
88 int overflow;
89
90 if (base < 0 || base == 1 || base > 36) return 0;
91
92 save = s = nptr;
93
94 /* Skip white space. */
95 while (isspaceW (*s))
96 ++s;
97 if (!*s) goto noconv;
98
99 /* Check for a sign. */
100 negative = 0;
101 if (*s == '-')
102 {
103 negative = 1;
104 ++s;
105 }
106 else if (*s == '+')
107 ++s;
108
109 /* Recognize number prefix and if BASE is zero, figure it out ourselves. */
110 if (*s == '0')
111 {
112 if ((base == 0 || base == 16) && toupperW(s[1]) == 'X')
113 {
114 s += 2;
115 base = 16;
116 }
117 else if (base == 0)
118 base = 8;
119 }
120 else if (base == 0)
121 base = 10;
122
123 /* Save the pointer so we can check later if anything happened. */
124 save = s;
125 end = NULL;
126
127 cutoff = ULONG_MAX / (unsigned long int) base;
128 cutlim = ULONG_MAX % (unsigned long int) base;
129
130 overflow = 0;
131 i = 0;
132 c = *s;
133 for (;c != '\0'; c = *++s)
134 {
135 if (s == end)
136 break;
137 if (c >= '0' && c <= '9')
138 c -= '0';
139 else if (isalphaW (c))
140 c = toupperW (c) - 'A' + 10;
141 else
142 break;
143 if ((int) c >= base)
144 break;
145 /* Check for overflow. */
146 if (i > cutoff || (i == cutoff && c > cutlim))
147 overflow = 1;
148 else
149 {
150 i *= (unsigned long int) base;
151 i += c;
152 }
153 }
154
155 /* Check if anything actually happened. */
156 if (s == save)
157 goto noconv;
158
159 /* Store in ENDPTR the address of one character
160 past the last character we converted. */
161 if (endptr != NULL)
162 *endptr = (WCHAR *)s;
163
164 /* Check for a value that is within the range of
165 `unsigned LONG int', but outside the range of `LONG int'. */
166 if (overflow == 0
167 && i > (negative
168 ? -((unsigned long int) (LONG_MIN + 1)) + 1
169 : (unsigned long int) LONG_MAX))
170 overflow = 1;
171
172 if (overflow)
173 {
174 return negative ? LONG_MIN : LONG_MAX;
175 }
176
177 /* Return the result of the appropriate sign. */
178 return negative ? -i : i;
179
180noconv:
181 /* We must handle a special case here: the base is 0 or 16 and the
182 first two characters are '0' and 'x', but the rest are not
183 hexadecimal digits. This is no error case. We return 0 and
184 ENDPTR points to the `x`. */
185 if (endptr != NULL)
186 {
187 if (save - nptr >= 2 && toupperW (save[-1]) == 'X'
188 && save[-2] == '0')
189 *endptr = (WCHAR *)&save[-1];
190 else
191 /* There was no number to convert. */
192 *endptr = (WCHAR *)nptr;
193 }
194
195 return 0L;
196}
197
198
199unsigned long int strtoulW( const WCHAR *nptr, WCHAR **endptr, int base )
200{
201 int negative;
202 register unsigned long int cutoff;
203 register unsigned int cutlim;
204 register unsigned long int i;
205 register const WCHAR *s;
206 register WCHAR c;
207 const WCHAR *save, *end;
208 int overflow;
209
210 if (base < 0 || base == 1 || base > 36) return 0;
211
212 save = s = nptr;
213
214 /* Skip white space. */
215 while (isspaceW (*s))
216 ++s;
217 if (!*s) goto noconv;
218
219 /* Check for a sign. */
220 negative = 0;
221 if (*s == '-')
222 {
223 negative = 1;
224 ++s;
225 }
226 else if (*s == '+')
227 ++s;
228
229 /* Recognize number prefix and if BASE is zero, figure it out ourselves. */
230 if (*s == '0')
231 {
232 if ((base == 0 || base == 16) && toupperW(s[1]) == 'X')
233 {
234 s += 2;
235 base = 16;
236 }
237 else if (base == 0)
238 base = 8;
239 }
240 else if (base == 0)
241 base = 10;
242
243 /* Save the pointer so we can check later if anything happened. */
244 save = s;
245 end = NULL;
246
247 cutoff = ULONG_MAX / (unsigned long int) base;
248 cutlim = ULONG_MAX % (unsigned long int) base;
249
250 overflow = 0;
251 i = 0;
252 c = *s;
253 for (;c != '\0'; c = *++s)
254 {
255 if (s == end)
256 break;
257 if (c >= '0' && c <= '9')
258 c -= '0';
259 else if (isalphaW (c))
260 c = toupperW (c) - 'A' + 10;
261 else
262 break;
263 if ((int) c >= base)
264 break;
265 /* Check for overflow. */
266 if (i > cutoff || (i == cutoff && c > cutlim))
267 overflow = 1;
268 else
269 {
270 i *= (unsigned long int) base;
271 i += c;
272 }
273 }
274
275 /* Check if anything actually happened. */
276 if (s == save)
277 goto noconv;
278
279 /* Store in ENDPTR the address of one character
280 past the last character we converted. */
281 if (endptr != NULL)
282 *endptr = (WCHAR *)s;
283
284 if (overflow)
285 {
286 return ULONG_MAX;
287 }
288
289 /* Return the result of the appropriate sign. */
290 return negative ? -i : i;
291
292noconv:
293 /* We must handle a special case here: the base is 0 or 16 and the
294 first two characters are '0' and 'x', but the rest are not
295 hexadecimal digits. This is no error case. We return 0 and
296 ENDPTR points to the `x`. */
297 if (endptr != NULL)
298 {
299 if (save - nptr >= 2 && toupperW (save[-1]) == 'X'
300 && save[-2] == '0')
301 *endptr = (WCHAR *)&save[-1];
302 else
303 /* There was no number to convert. */
304 *endptr = (WCHAR *)nptr;
305 }
306
307 return 0L;
308}
309
310
311/* format a WCHAR string according to a printf format; helper for vsnprintfW */
312static int format_string( WCHAR *buffer, size_t len, const char *format, const WCHAR *str )
313{
314 size_t count = 0;
315 int i, left_align = 0, width = 0, max = 0;
316
317 assert( *format == '%' );
318 format++; /* skip '%' */
319
320 while (*format == '0' || *format == '+' || *format == '-' || *format == ' ' || *format == '#')
321 {
322 if (*format == '-') left_align = 1;
323 format++;
324 }
325
326 while (isdigit(*format)) width = width * 10 + *format++ - '0';
327
328 if (*format == '.')
329 {
330 format++;
331 while (isdigit(*format)) max = max * 10 + *format++ - '0';
332 for (i = 0; i < max; i++) if (!str[i]) max = i;
333 }
334 else max = strlenW(str);
335
336 if (*format == 'h' || *format == 'l') format++;
337
338 assert( *format == 's' );
339
340 if (!left_align && width > max)
341 {
342 if ((count += width - max) >= len) return -1;
343 for (i = 0; i < width - max; i++) *buffer++ = ' ';
344 }
345
346 if ((count += max) >= len) return -1;
347 memcpy( buffer, str, max * sizeof(WCHAR) );
348 buffer += max;
349
350 if (left_align && width > max)
351 {
352 if ((count += width - max) >= len) return -1;
353 for (i = 0; i < width - max; i++) *buffer++ = ' ';
354 }
355 return count;
356}
357
358int vsnprintfW(WCHAR *str, size_t len, const WCHAR *format, va_list valist)
359{
360 unsigned int written = 0;
361 const WCHAR *iter = format;
362 char bufa[256], fmtbufa[64], *fmta;
363
364 while (*iter)
365 {
366 while (*iter && *iter != '%')
367 {
368 if (written++ >= len)
369 return -1;
370 *str++ = *iter++;
371 }
372 if (*iter == '%')
373 {
374 if (iter[1] == '%')
375 {
376 if (written++ >= len)
377 return -1;
378 *str++ = '%'; /* "%%"->'%' */
379 iter += 2;
380 continue;
381 }
382
383 fmta = fmtbufa;
384 *fmta++ = *iter++;
385 while (*iter == '0' ||
386 *iter == '+' ||
387 *iter == '-' ||
388 *iter == ' ' ||
389 *iter == '*' ||
390 *iter == '#')
391 {
392 if (*iter == '*')
393 {
394 char *buffiter = bufa;
395 int fieldlen = va_arg(valist, int);
396 sprintf(buffiter, "%d", fieldlen);
397 while (*buffiter)
398 *fmta++ = *buffiter++;
399 }
400 else
401 *fmta++ = *iter;
402 iter++;
403 }
404
405 while (isdigit(*iter))
406 *fmta++ = *iter++;
407
408 if (*iter == '.')
409 {
410 *fmta++ = *iter++;
411 if (*iter == '*')
412 {
413 char *buffiter = bufa;
414 int fieldlen = va_arg(valist, int);
415 sprintf(buffiter, "%d", fieldlen);
416 while (*buffiter)
417 *fmta++ = *buffiter++;
418 }
419 else
420 while (isdigit(*iter))
421 *fmta++ = *iter++;
422 }
423 if (*iter == 'h' || *iter == 'l')
424 *fmta++ = *iter++;
425
426 switch (*iter)
427 {
428 case 's':
429 {
430 static const WCHAR none[] = { '(','n','u','l','l',')',0 };
431 const WCHAR *wstr = va_arg(valist, const WCHAR *);
432 int count;
433
434 *fmta++ = 's';
435 *fmta = 0;
436 count = format_string( str, len - written, fmtbufa, wstr ? wstr : none );
437 if (count == -1) return -1;
438 str += count;
439 written += count;
440 iter++;
441 break;
442 }
443
444 case 'c':
445 {
446 WCHAR wstr[2];
447 int count;
448
449 wstr[0] = va_arg(valist, int);
450 wstr[1] = 0;
451 *fmta++ = 's';
452 *fmta = 0;
453 count = format_string( str, len - written, fmtbufa, wstr );
454 if (count == -1) return -1;
455 str += count;
456 written += count;
457 iter++;
458 break;
459 }
460
461 default:
462 {
463 /* For non wc types, use system sprintf and append to wide char output */
464 /* FIXME: for unrecognised types, should ignore % when printing */
465 char *bufaiter = bufa;
466 if (*iter == 'p')
467 sprintf(bufaiter, "%0*lX", 2 * (int)sizeof(void*),
468 (unsigned long)va_arg(valist, void *));
469 else
470 {
471 *fmta++ = *iter;
472 *fmta = '\0';
473 if (*iter == 'a' || *iter == 'A' ||
474 *iter == 'e' || *iter == 'E' ||
475 *iter == 'f' || *iter == 'F' ||
476 *iter == 'g' || *iter == 'G')
477 sprintf(bufaiter, fmtbufa, va_arg(valist, double));
478 else
479 {
480 /* FIXME: On 32 bit systems this doesn't handle int 64's. */
481 sprintf(bufaiter, fmtbufa, va_arg(valist, void *));
482 }
483 }
484 while (*bufaiter)
485 {
486 if (written++ >= len)
487 return -1;
488 *str++ = *bufaiter++;
489 }
490 iter++;
491 break;
492 }
493 }
494 }
495 }
496 if (written >= len)
497 return -1;
498 *str++ = 0;
499 return (int)written;
500}
501
502int vsprintfW( WCHAR *str, const WCHAR *format, va_list valist )
503{
504 return vsnprintfW( str, INT_MAX, format, valist );
505}
506
507int snprintfW( WCHAR *str, size_t len, const WCHAR *format, ...)
508{
509 int retval;
510 va_list valist;
511 va_start(valist, format);
512 retval = vsnprintfW(str, len, format, valist);
513 va_end(valist);
514 return retval;
515}
516
517int sprintfW( WCHAR *str, const WCHAR *format, ...)
518{
519 int retval;
520 va_list valist;
521 va_start(valist, format);
522 retval = vsnprintfW(str, INT_MAX, format, valist);
523 va_end(valist);
524 return retval;
525}
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette