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
24 #define WINE_UNICODE_INLINE /* nothing */
25 #include "wine/unicode.h"
27 int strcmpiW( const WCHAR
*str1
, const WCHAR
*str2
)
31 int ret
= tolowerW(*str1
) - tolowerW(*str2
);
32 if (ret
|| !*str1
) return ret
;
38 int strncmpiW( const WCHAR
*str1
, const WCHAR
*str2
, int n
)
41 for ( ; n
> 0; n
--, str1
++, str2
++)
42 if ((ret
= tolowerW(*str1
) - tolowerW(*str2
)) || !*str1
) break;
46 int memicmpW( const WCHAR
*str1
, const WCHAR
*str2
, int n
)
49 for ( ; n
> 0; n
--, str1
++, str2
++)
50 if ((ret
= tolowerW(*str1
) - tolowerW(*str2
))) break;
54 WCHAR
*strstrW( const WCHAR
*str
, const WCHAR
*sub
)
58 const WCHAR
*p1
= str
, *p2
= sub
;
59 while (*p1
&& *p2
&& *p1
== *p2
) { p1
++; p2
++; }
60 if (!*p2
) return (WCHAR
*)str
;
66 /* strtolW and strtoulW implementation based on the GNU C library code */
67 /* Copyright (C) 1991,92,94,95,96,97,98,99,2000,2001 Free Software Foundation, Inc. */
69 long int strtolW( const WCHAR
*nptr
, WCHAR
**endptr
, int base
)
72 register unsigned long int cutoff
;
73 register unsigned int cutlim
;
74 register unsigned long int i
;
75 register const WCHAR
*s
;
77 const WCHAR
*save
, *end
;
80 if (base
< 0 || base
== 1 || base
> 36) return 0;
84 /* Skip white space. */
89 /* Check for a sign. */
99 /* Recognize number prefix and if BASE is zero, figure it out ourselves. */
102 if ((base
== 0 || base
== 16) && toupperW(s
[1]) == 'X')
113 /* Save the pointer so we can check later if anything happened. */
117 cutoff
= ULONG_MAX
/ (unsigned long int) base
;
118 cutlim
= ULONG_MAX
% (unsigned long int) base
;
123 for (;c
!= '\0'; c
= *++s
)
127 if (c
>= '0' && c
<= '9')
129 else if (isalphaW (c
))
130 c
= toupperW (c
) - 'A' + 10;
135 /* Check for overflow. */
136 if (i
> cutoff
|| (i
== cutoff
&& c
> cutlim
))
140 i
*= (unsigned long int) base
;
145 /* Check if anything actually happened. */
149 /* Store in ENDPTR the address of one character
150 past the last character we converted. */
152 *endptr
= (WCHAR
*)s
;
154 /* Check for a value that is within the range of
155 `unsigned LONG int', but outside the range of `LONG int'. */
158 ? -((unsigned long int) (LONG_MIN
+ 1)) + 1
159 : (unsigned long int) LONG_MAX
))
164 return negative
? LONG_MIN
: LONG_MAX
;
167 /* Return the result of the appropriate sign. */
168 return negative
? -i
: i
;
171 /* We must handle a special case here: the base is 0 or 16 and the
172 first two characters are '0' and 'x', but the rest are not
173 hexadecimal digits. This is no error case. We return 0 and
174 ENDPTR points to the `x`. */
177 if (save
- nptr
>= 2 && toupperW (save
[-1]) == 'X'
179 *endptr
= (WCHAR
*)&save
[-1];
181 /* There was no number to convert. */
182 *endptr
= (WCHAR
*)nptr
;
189 unsigned long int strtoulW( const WCHAR
*nptr
, WCHAR
**endptr
, int base
)
192 register unsigned long int cutoff
;
193 register unsigned int cutlim
;
194 register unsigned long int i
;
195 register const WCHAR
*s
;
197 const WCHAR
*save
, *end
;
200 if (base
< 0 || base
== 1 || base
> 36) return 0;
204 /* Skip white space. */
205 while (isspaceW (*s
))
207 if (!*s
) goto noconv
;
209 /* Check for a sign. */
219 /* Recognize number prefix and if BASE is zero, figure it out ourselves. */
222 if ((base
== 0 || base
== 16) && toupperW(s
[1]) == 'X')
233 /* Save the pointer so we can check later if anything happened. */
237 cutoff
= ULONG_MAX
/ (unsigned long int) base
;
238 cutlim
= ULONG_MAX
% (unsigned long int) base
;
243 for (;c
!= '\0'; c
= *++s
)
247 if (c
>= '0' && c
<= '9')
249 else if (isalphaW (c
))
250 c
= toupperW (c
) - 'A' + 10;
255 /* Check for overflow. */
256 if (i
> cutoff
|| (i
== cutoff
&& c
> cutlim
))
260 i
*= (unsigned long int) base
;
265 /* Check if anything actually happened. */
269 /* Store in ENDPTR the address of one character
270 past the last character we converted. */
272 *endptr
= (WCHAR
*)s
;
279 /* Return the result of the appropriate sign. */
280 return negative
? -i
: i
;
283 /* We must handle a special case here: the base is 0 or 16 and the
284 first two characters are '0' and 'x', but the rest are not
285 hexadecimal digits. This is no error case. We return 0 and
286 ENDPTR points to the `x`. */
289 if (save
- nptr
>= 2 && toupperW (save
[-1]) == 'X'
291 *endptr
= (WCHAR
*)&save
[-1];
293 /* There was no number to convert. */
294 *endptr
= (WCHAR
*)nptr
;
301 int vsnprintfW(WCHAR
*str
, size_t len
, const WCHAR
*format
, va_list valist
)
303 unsigned int written
= 0;
304 const WCHAR
*iter
= format
;
305 char bufa
[256], fmtbufa
[64], *fmta
;
309 while (*iter
&& *iter
!= '%')
311 if (written
++ >= len
)
319 if (written
++ >= len
)
321 *str
++ = '%'; /* "%%"->'%' */
328 while (*iter
== '0' ||
337 char *buffiter
= bufa
;
338 int fieldlen
= va_arg(valist
, int);
339 sprintf(buffiter
, "%d", fieldlen
);
341 *fmta
++ = *buffiter
++;
348 while (isdigit(*iter
))
356 char *buffiter
= bufa
;
357 int fieldlen
= va_arg(valist
, int);
358 sprintf(buffiter
, "%d", fieldlen
);
360 *fmta
++ = *buffiter
++;
363 while (isdigit(*iter
))
366 if (*iter
== 'h' || *iter
== 'l')
373 static const WCHAR none
[] = { '(','n','u','l','l',')',0 };
374 const WCHAR
*wstr
= va_arg(valist
, const WCHAR
*);
375 const WCHAR
*striter
= wstr
? wstr
: none
;
378 if (written
++ >= len
)
387 if (written
++ >= len
)
389 *str
++ = (WCHAR
)va_arg(valist
, int);
395 /* For non wc types, use system sprintf and append to wide char output */
396 /* FIXME: for unrecognised types, should ignore % when printing */
397 char *bufaiter
= bufa
;
399 sprintf(bufaiter
, "%08lX", va_arg(valist
, long));
404 if (*iter
== 'a' || *iter
== 'A' ||
405 *iter
== 'e' || *iter
== 'E' ||
406 *iter
== 'f' || *iter
== 'F' ||
407 *iter
== 'g' || *iter
== 'G')
408 sprintf(bufaiter
, fmtbufa
, va_arg(valist
, double));
411 /* FIXME: On 32 bit systems this doesn't handle int 64's.
412 * on 64 bit systems this doesn't work for 32 bit types
414 sprintf(bufaiter
, fmtbufa
, va_arg(valist
, void *));
419 if (written
++ >= len
)
421 *str
++ = *bufaiter
++;
435 int vsprintfW( WCHAR
*str
, const WCHAR
*format
, va_list valist
)
437 return vsnprintfW( str
, INT_MAX
, format
, valist
);
440 int snprintfW( WCHAR
*str
, size_t len
, const WCHAR
*format
, ...)
444 va_start(valist
, format
);
445 retval
= vsnprintfW(str
, len
, format
, valist
);
450 int sprintfW( WCHAR
*str
, const WCHAR
*format
, ...)
454 va_start(valist
, format
);
455 retval
= vsnprintfW(str
, INT_MAX
, format
, valist
);