2 * Unicode string manipulation functions
4 * Copyright 2000 Alexandre Julliard
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.
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.
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
25 #define WINE_UNICODE_INLINE /* nothing */
26 #include "wine/unicode.h"
28 int strcmpiW( const WCHAR
*str1
, const WCHAR
*str2
)
32 int ret
= tolowerW(*str1
) - tolowerW(*str2
);
33 if (ret
|| !*str1
) return ret
;
39 int strncmpiW( const WCHAR
*str1
, const WCHAR
*str2
, int n
)
42 for ( ; n
> 0; n
--, str1
++, str2
++)
43 if ((ret
= tolowerW(*str1
) - tolowerW(*str2
)) || !*str1
) break;
47 int memicmpW( const WCHAR
*str1
, const WCHAR
*str2
, int n
)
50 for ( ; n
> 0; n
--, str1
++, str2
++)
51 if ((ret
= tolowerW(*str1
) - tolowerW(*str2
))) break;
55 WCHAR
*strstrW( const WCHAR
*str
, const WCHAR
*sub
)
59 const WCHAR
*p1
= str
, *p2
= sub
;
60 while (*p1
&& *p2
&& *p1
== *p2
) { p1
++; p2
++; }
61 if (!*p2
) return (WCHAR
*)str
;
67 /* strtolW and strtoulW implementation based on the GNU C library code */
68 /* Copyright (C) 1991,92,94,95,96,97,98,99,2000,2001 Free Software Foundation, Inc. */
70 long int strtolW( const WCHAR
*nptr
, WCHAR
**endptr
, int base
)
73 register unsigned long int cutoff
;
74 register unsigned int cutlim
;
75 register unsigned long int i
;
76 register const WCHAR
*s
;
78 const WCHAR
*save
, *end
;
81 if (base
< 0 || base
== 1 || base
> 36) return 0;
85 /* Skip white space. */
90 /* Check for a sign. */
100 /* Recognize number prefix and if BASE is zero, figure it out ourselves. */
103 if ((base
== 0 || base
== 16) && toupperW(s
[1]) == 'X')
114 /* Save the pointer so we can check later if anything happened. */
118 cutoff
= ULONG_MAX
/ (unsigned long int) base
;
119 cutlim
= ULONG_MAX
% (unsigned long int) base
;
124 for (;c
!= '\0'; c
= *++s
)
128 if (c
>= '0' && c
<= '9')
130 else if (isalphaW (c
))
131 c
= toupperW (c
) - 'A' + 10;
136 /* Check for overflow. */
137 if (i
> cutoff
|| (i
== cutoff
&& c
> cutlim
))
141 i
*= (unsigned long int) base
;
146 /* Check if anything actually happened. */
150 /* Store in ENDPTR the address of one character
151 past the last character we converted. */
153 *endptr
= (WCHAR
*)s
;
155 /* Check for a value that is within the range of
156 `unsigned LONG int', but outside the range of `LONG int'. */
159 ? -((unsigned long int) (LONG_MIN
+ 1)) + 1
160 : (unsigned long int) LONG_MAX
))
165 return negative
? LONG_MIN
: LONG_MAX
;
168 /* Return the result of the appropriate sign. */
169 return negative
? -i
: i
;
172 /* We must handle a special case here: the base is 0 or 16 and the
173 first two characters are '0' and 'x', but the rest are not
174 hexadecimal digits. This is no error case. We return 0 and
175 ENDPTR points to the `x`. */
178 if (save
- nptr
>= 2 && toupperW (save
[-1]) == 'X'
180 *endptr
= (WCHAR
*)&save
[-1];
182 /* There was no number to convert. */
183 *endptr
= (WCHAR
*)nptr
;
190 unsigned long int strtoulW( const WCHAR
*nptr
, WCHAR
**endptr
, int base
)
193 register unsigned long int cutoff
;
194 register unsigned int cutlim
;
195 register unsigned long int i
;
196 register const WCHAR
*s
;
198 const WCHAR
*save
, *end
;
201 if (base
< 0 || base
== 1 || base
> 36) return 0;
205 /* Skip white space. */
206 while (isspaceW (*s
))
208 if (!*s
) goto noconv
;
210 /* Check for a sign. */
220 /* Recognize number prefix and if BASE is zero, figure it out ourselves. */
223 if ((base
== 0 || base
== 16) && toupperW(s
[1]) == 'X')
234 /* Save the pointer so we can check later if anything happened. */
238 cutoff
= ULONG_MAX
/ (unsigned long int) base
;
239 cutlim
= ULONG_MAX
% (unsigned long int) base
;
244 for (;c
!= '\0'; c
= *++s
)
248 if (c
>= '0' && c
<= '9')
250 else if (isalphaW (c
))
251 c
= toupperW (c
) - 'A' + 10;
256 /* Check for overflow. */
257 if (i
> cutoff
|| (i
== cutoff
&& c
> cutlim
))
261 i
*= (unsigned long int) base
;
266 /* Check if anything actually happened. */
270 /* Store in ENDPTR the address of one character
271 past the last character we converted. */
273 *endptr
= (WCHAR
*)s
;
280 /* Return the result of the appropriate sign. */
281 return negative
? -i
: i
;
284 /* We must handle a special case here: the base is 0 or 16 and the
285 first two characters are '0' and 'x', but the rest are not
286 hexadecimal digits. This is no error case. We return 0 and
287 ENDPTR points to the `x`. */
290 if (save
- nptr
>= 2 && toupperW (save
[-1]) == 'X'
292 *endptr
= (WCHAR
*)&save
[-1];
294 /* There was no number to convert. */
295 *endptr
= (WCHAR
*)nptr
;
302 /* format a WCHAR string according to a printf format; helper for vsnprintfW */
303 static int format_string( WCHAR
*buffer
, size_t len
, const char *format
, const WCHAR
*str
)
306 int i
, left_align
= 0, width
= 0, max
= 0;
308 assert( *format
== '%' );
309 format
++; /* skip '%' */
311 while (*format
== '0' || *format
== '+' || *format
== '-' || *format
== ' ' || *format
== '#')
313 if (*format
== '-') left_align
= 1;
317 while (isdigit(*format
)) width
= width
* 10 + *format
++ - '0';
322 while (isdigit(*format
)) max
= max
* 10 + *format
++ - '0';
323 for (i
= 0; i
< max
; i
++) if (!str
[i
]) max
= i
;
325 else max
= strlenW(str
);
327 if (*format
== 'h' || *format
== 'l') format
++;
329 assert( *format
== 's' );
331 if (!left_align
&& width
> max
)
333 if ((count
+= width
- max
) >= len
) return -1;
334 for (i
= 0; i
< width
- max
; i
++) *buffer
++ = ' ';
337 if ((count
+= max
) >= len
) return -1;
338 memcpy( buffer
, str
, max
* sizeof(WCHAR
) );
341 if (left_align
&& width
> max
)
343 if ((count
+= width
- max
) >= len
) return -1;
344 for (i
= 0; i
< width
- max
; i
++) *buffer
++ = ' ';
349 int vsnprintfW(WCHAR
*str
, size_t len
, const WCHAR
*format
, va_list valist
)
351 unsigned int written
= 0;
352 const WCHAR
*iter
= format
;
353 char bufa
[256], fmtbufa
[64], *fmta
;
357 while (*iter
&& *iter
!= '%')
359 if (written
++ >= len
)
367 if (written
++ >= len
)
369 *str
++ = '%'; /* "%%"->'%' */
376 while (*iter
== '0' ||
385 char *buffiter
= bufa
;
386 int fieldlen
= va_arg(valist
, int);
387 sprintf(buffiter
, "%d", fieldlen
);
389 *fmta
++ = *buffiter
++;
396 while (isdigit(*iter
))
404 char *buffiter
= bufa
;
405 int fieldlen
= va_arg(valist
, int);
406 sprintf(buffiter
, "%d", fieldlen
);
408 *fmta
++ = *buffiter
++;
411 while (isdigit(*iter
))
414 if (*iter
== 'h' || *iter
== 'l')
421 static const WCHAR none
[] = { '(','n','u','l','l',')',0 };
422 const WCHAR
*wstr
= va_arg(valist
, const WCHAR
*);
427 count
= format_string( str
, len
- written
, fmtbufa
, wstr
? wstr
: none
);
428 if (count
== -1) return -1;
440 wstr
[0] = va_arg(valist
, int);
444 count
= format_string( str
, len
- written
, fmtbufa
, wstr
);
445 if (count
== -1) return -1;
454 /* For non wc types, use system sprintf and append to wide char output */
455 /* FIXME: for unrecognised types, should ignore % when printing */
456 char *bufaiter
= bufa
;
458 sprintf(bufaiter
, "%0*lX", 2 * (int)sizeof(void*),
459 (unsigned long)va_arg(valist
, void *));
464 if (*iter
== 'a' || *iter
== 'A' ||
465 *iter
== 'e' || *iter
== 'E' ||
466 *iter
== 'f' || *iter
== 'F' ||
467 *iter
== 'g' || *iter
== 'G')
468 sprintf(bufaiter
, fmtbufa
, va_arg(valist
, double));
471 /* FIXME: On 32 bit systems this doesn't handle int 64's. */
472 sprintf(bufaiter
, fmtbufa
, va_arg(valist
, void *));
477 if (written
++ >= len
)
479 *str
++ = *bufaiter
++;
493 int vsprintfW( WCHAR
*str
, const WCHAR
*format
, va_list valist
)
495 return vsnprintfW( str
, INT_MAX
, format
, valist
);
498 int snprintfW( WCHAR
*str
, size_t len
, const WCHAR
*format
, ...)
502 va_start(valist
, format
);
503 retval
= vsnprintfW(str
, len
, format
, valist
);
508 int sprintfW( WCHAR
*str
, const WCHAR
*format
, ...)
512 va_start(valist
, format
);
513 retval
= vsnprintfW(str
, INT_MAX
, format
, valist
);