VirtualBox

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

Last change on this file since 33085 was 25949, checked in by vboxsync, 15 years ago

crOpenGL: update to wine 1.1.36 and disable unnecessary fbo state poll

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