source: branches/gcc-kmk/src/ntdll/wcstring.c@ 21879

Last change on this file since 21879 was 21879, checked in by dmik, 14 years ago

Add snwprintf to minivcrt.h.

This is mainly to be used instead of POSIX snprintf which is
missing from the current kLIBC runtime.

File size: 17.0 KB
Line 
1/*
2 * NTDLL wide-char functions
3 *
4 * Copyright 2000 Alexandre Julliard
5 * Copyright 2000 Jon Griffiths
6 * Copyright 2003 Thomas Mertes
7 *
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
12 *
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 */
22
23#include "config.h"
24
25#include <ctype.h>
26#include <stdlib.h>
27#include <string.h>
28#include <stdio.h>
29#include <limits.h>
30
31#include "winternl.h"
32#include "wine/unicode.h"
33#include "wine/debug.h"
34
35WINE_DEFAULT_DEBUG_CHANNEL(ntdll);
36
37
38/*********************************************************************
39 * _wcsicmp (NTDLL.@)
40 */
41INT __cdecl NTDLL__wcsicmp( LPCWSTR str1, LPCWSTR str2 )
42{
43 return strcmpiW( str1, str2 );
44}
45
46
47/*********************************************************************
48 * _wcslwr (NTDLL.@)
49 */
50LPWSTR __cdecl NTDLL__wcslwr( LPWSTR str )
51{
52 return strlwrW( str );
53}
54
55
56/*********************************************************************
57 * _wcsnicmp (NTDLL.@)
58 */
59INT __cdecl NTDLL__wcsnicmp( LPCWSTR str1, LPCWSTR str2, INT n )
60{
61 return strncmpiW( str1, str2, n );
62}
63
64
65/*********************************************************************
66 * _wcsupr (NTDLL.@)
67 */
68LPWSTR __cdecl NTDLL__wcsupr( LPWSTR str )
69{
70 return struprW( str );
71}
72
73
74/*********************************************************************
75 * towlower (NTDLL.@)
76 */
77WCHAR __cdecl NTDLL_towlower( WCHAR ch )
78{
79 return tolowerW(ch);
80}
81
82
83/*********************************************************************
84 * towupper (NTDLL.@)
85 */
86WCHAR __cdecl NTDLL_towupper( WCHAR ch )
87{
88 return toupperW(ch);
89}
90
91
92/***********************************************************************
93 * wcscat (NTDLL.@)
94 */
95LPWSTR __cdecl NTDLL_wcscat( LPWSTR dst, LPCWSTR src )
96{
97 return strcatW( dst, src );
98}
99
100
101/*********************************************************************
102 * wcschr (NTDLL.@)
103 */
104LPWSTR __cdecl NTDLL_wcschr( LPCWSTR str, WCHAR ch )
105{
106 return strchrW( str, ch );
107}
108
109
110/*********************************************************************
111 * wcscmp (NTDLL.@)
112 */
113INT __cdecl NTDLL_wcscmp( LPCWSTR str1, LPCWSTR str2 )
114{
115 return strcmpW( str1, str2 );
116}
117
118
119/***********************************************************************
120 * wcscpy (NTDLL.@)
121 */
122LPWSTR __cdecl NTDLL_wcscpy( LPWSTR dst, LPCWSTR src )
123{
124 return strcpyW( dst, src );
125}
126
127
128/*********************************************************************
129 * wcscspn (NTDLL.@)
130 */
131INT __cdecl NTDLL_wcscspn( LPCWSTR str, LPCWSTR reject )
132{
133 LPCWSTR start = str;
134 while (*str)
135 {
136 LPCWSTR p = reject;
137 while (*p && (*p != *str)) p++;
138 if (*p) break;
139 str++;
140 }
141 return str - start;
142}
143
144
145/***********************************************************************
146 * wcslen (NTDLL.@)
147 */
148INT __cdecl NTDLL_wcslen( LPCWSTR str )
149{
150 return strlenW( str );
151}
152
153
154/*********************************************************************
155 * wcsncat (NTDLL.@)
156 */
157LPWSTR __cdecl NTDLL_wcsncat( LPWSTR s1, LPCWSTR s2, INT n )
158{
159 LPWSTR ret = s1;
160 while (*s1) s1++;
161 while (n-- > 0) if (!(*s1++ = *s2++)) return ret;
162 *s1 = 0;
163 return ret;
164}
165
166
167/*********************************************************************
168 * wcsncmp (NTDLL.@)
169 */
170INT __cdecl NTDLL_wcsncmp( LPCWSTR str1, LPCWSTR str2, INT n )
171{
172 return strncmpW( str1, str2, n );
173}
174
175
176/*********************************************************************
177 * wcsncpy (NTDLL.@)
178 */
179LPWSTR __cdecl NTDLL_wcsncpy( LPWSTR s1, LPCWSTR s2, INT n )
180{
181 return strncpyW( s1, s2, n );
182}
183
184
185/*********************************************************************
186 * wcspbrk (NTDLL.@)
187 */
188LPWSTR __cdecl NTDLL_wcspbrk( LPCWSTR str, LPCWSTR accept )
189{
190 LPCWSTR p;
191 while (*str)
192 {
193 for (p = accept; *p; p++) if (*p == *str) return (LPWSTR)str;
194 str++;
195 }
196 return NULL;
197}
198
199
200/*********************************************************************
201 * wcsrchr (NTDLL.@)
202 */
203LPWSTR __cdecl NTDLL_wcsrchr( LPWSTR str, WCHAR ch )
204{
205 LPWSTR last = NULL;
206 while (*str)
207 {
208 if (*str == ch) last = str;
209 str++;
210 }
211 return last;
212}
213
214
215/*********************************************************************
216 * wcsspn (NTDLL.@)
217 */
218INT __cdecl NTDLL_wcsspn( LPCWSTR str, LPCWSTR accept )
219{
220 LPCWSTR start = str;
221 while (*str)
222 {
223 LPCWSTR p = accept;
224 while (*p && (*p != *str)) p++;
225 if (!*p) break;
226 str++;
227 }
228 return str - start;
229}
230
231
232/*********************************************************************
233 * wcsstr (NTDLL.@)
234 */
235LPWSTR __cdecl NTDLL_wcsstr( LPCWSTR str, LPCWSTR sub )
236{
237 return strstrW( str, sub );
238}
239
240
241/*********************************************************************
242 * wcstok (NTDLL.@)
243 */
244LPWSTR __cdecl NTDLL_wcstok( LPWSTR str, LPCWSTR delim )
245{
246 static LPWSTR next = NULL;
247 LPWSTR ret;
248
249 if (!str)
250 if (!(str = next)) return NULL;
251
252 while (*str && NTDLL_wcschr( delim, *str )) str++;
253 if (!*str) return NULL;
254 ret = str++;
255 while (*str && !NTDLL_wcschr( delim, *str )) str++;
256 if (*str) *str++ = 0;
257 next = str;
258 return ret;
259}
260
261
262/*********************************************************************
263 * wcstombs (NTDLL.@)
264 */
265INT __cdecl NTDLL_wcstombs( LPSTR dst, LPCWSTR src, INT n )
266{
267 DWORD len;
268
269 if (!dst)
270 {
271 RtlUnicodeToMultiByteSize( &len, src, strlenW(src)*sizeof(WCHAR) );
272 return len;
273 }
274 else
275 {
276 if (n <= 0) return 0;
277 RtlUnicodeToMultiByteN( dst, n, &len, src, strlenW(src)*sizeof(WCHAR) );
278 if (len < n) dst[len] = 0;
279 }
280 return len;
281}
282
283
284/*********************************************************************
285 * mbstowcs (NTDLL.@)
286 */
287INT __cdecl NTDLL_mbstowcs( LPWSTR dst, LPCSTR src, INT n )
288{
289 DWORD len;
290
291 if (!dst)
292 {
293 RtlMultiByteToUnicodeSize( &len, src, strlen(src) );
294 }
295 else
296 {
297 if (n <= 0) return 0;
298 RtlMultiByteToUnicodeN( dst, n*sizeof(WCHAR), &len, src, strlen(src) );
299 if (len / sizeof(WCHAR) < n) dst[len / sizeof(WCHAR)] = 0;
300 }
301 return len / sizeof(WCHAR);
302}
303
304
305/*********************************************************************
306 * wcstol (NTDLL.@)
307 */
308long __cdecl NTDLL_wcstol(LPCWSTR s,LPWSTR *end,INT base)
309{
310 return strtolW( s, end, base );
311}
312
313
314/*********************************************************************
315 * wcstoul (NTDLL.@)
316 */
317unsigned long __cdecl NTDLL_wcstoul(LPCWSTR s,LPWSTR *end,INT base)
318{
319 return strtoulW( s, end, base );
320}
321
322
323/*********************************************************************
324 * iswctype (NTDLL.@)
325 */
326INT __cdecl NTDLL_iswctype( WCHAR wc, WCHAR wct )
327{
328 return (get_char_typeW(wc) & 0xfff) & wct;
329}
330
331
332/*********************************************************************
333 * iswalpha (NTDLL.@)
334 */
335INT __cdecl NTDLL_iswalpha( WCHAR wc )
336{
337 return get_char_typeW(wc) & C1_ALPHA;
338}
339
340/*********************************************************************
341 * iswdigit (NTDLL.@)
342 *
343 * Checks if an unicode char wc is a digit
344 *
345 * RETURNS
346 * TRUE: The unicode char wc is a digit.
347 * FALSE: Otherwise
348 */
349INT __cdecl NTDLL_iswdigit( WCHAR wc )
350{
351 return isdigitW(wc);
352}
353
354
355/*********************************************************************
356 * iswlower (NTDLL.@)
357 *
358 * Checks if an unicode char wc is a lower case letter
359 *
360 * RETURNS
361 * TRUE: The unicode char wc is a lower case letter.
362 * FALSE: Otherwise
363 */
364INT __cdecl NTDLL_iswlower( WCHAR wc )
365{
366 return islowerW(wc);
367}
368
369
370/*********************************************************************
371 * iswspace (NTDLL.@)
372 *
373 * Checks if an unicode char wc is a white space character
374 *
375 * RETURNS
376 * TRUE: The unicode char wc is a white space character.
377 * FALSE: Otherwise
378 */
379INT __cdecl NTDLL_iswspace( WCHAR wc )
380{
381 return isspaceW(wc);
382}
383
384
385/*********************************************************************
386 * iswxdigit (NTDLL.@)
387 *
388 * Checks if an unicode char wc is an extended digit
389 *
390 * RETURNS
391 * TRUE: The unicode char wc is an extended digit.
392 * FALSE: Otherwise
393 */
394INT __cdecl NTDLL_iswxdigit( WCHAR wc )
395{
396 return isxdigitW(wc);
397}
398
399
400/*********************************************************************
401 * _ultow (NTDLL.@)
402 *
403 * Converts an unsigned long integer to an unicode string.
404 *
405 * Assigns a '\0' terminated string to str and returns str.
406 * Does not check if radix is in the range of 2 to 36 (as native DLL).
407 * For str == NULL just returns NULL (as native DLL).
408 */
409LPWSTR __cdecl _ultow( unsigned long value, LPWSTR str, INT radix )
410{
411 WCHAR buffer[33];
412 PWCHAR pos;
413 WCHAR digit;
414
415 pos = &buffer[32];
416 *pos = '\0';
417
418 do {
419 digit = value % radix;
420 value = value / radix;
421 if (digit < 10) {
422 *--pos = '0' + digit;
423 } else {
424 *--pos = 'a' + digit - 10;
425 } /* if */
426 } while (value != 0L);
427
428 if (str != NULL) {
429 memcpy(str, pos, (&buffer[32] - pos + 1) * sizeof(WCHAR));
430 } /* if */
431 return str;
432}
433
434
435/*********************************************************************
436 * _ltow (NTDLL.@)
437 *
438 * Converts a long integer to an unicode string.
439 *
440 * RETURNS
441 * Always returns str.
442 *
443 * NOTES
444 * Converts value to a '\0' terminated wstring which is copied to str.
445 * The maximum length of the copied str is 33 bytes. If radix
446 * is 10 and value is negative, the value is converted with sign.
447 * Does not check if radix is in the range of 2 to 36.
448 * If str is NULL it just returns NULL.
449 */
450LPWSTR __cdecl _ltow(
451 long value, /* [I] Value to be converted */
452 LPWSTR str, /* [O] Destination for the converted value */
453 INT radix) /* [I] Number base for conversion */
454{
455 unsigned long val;
456 int negative;
457 WCHAR buffer[33];
458 PWCHAR pos;
459 WCHAR digit;
460
461 if (value < 0 && radix == 10) {
462 negative = 1;
463 val = -value;
464 } else {
465 negative = 0;
466 val = value;
467 } /* if */
468
469 pos = &buffer[32];
470 *pos = '\0';
471
472 do {
473 digit = val % radix;
474 val = val / radix;
475 if (digit < 10) {
476 *--pos = '0' + digit;
477 } else {
478 *--pos = 'a' + digit - 10;
479 } /* if */
480 } while (val != 0L);
481
482 if (negative) {
483 *--pos = '-';
484 } /* if */
485
486 if (str != NULL) {
487 memcpy(str, pos, (&buffer[32] - pos + 1) * sizeof(WCHAR));
488 } /* if */
489 return str;
490}
491
492
493
494/*********************************************************************
495 * _itow (NTDLL.@)
496 *
497 * Converts an integer to an unicode string.
498 *
499 * RETURNS
500 * Always returns str.
501 *
502 * NOTES
503 * Converts value to a '\0' terminated wstring which is copied to str.
504 * The maximum length of the copied str is 33 bytes. If radix
505 * is 10 and value is negative, the value is converted with sign.
506 * Does not check if radix is in the range of 2 to 36.
507 * If str is NULL it just returns NULL.
508 *
509 * DIFFERENCES
510 * - The native function crashes when the string is longer than 19 chars.
511 * This function does not have this bug.
512 */
513LPWSTR __cdecl _itow(
514 int value, /* [I] Value to be converted */
515 LPWSTR str, /* [O] Destination for the converted value */
516 INT radix) /* [I] Number base for conversion */
517{
518 return _ltow(value, str, radix);
519}
520
521
522/*********************************************************************
523 * _ui64tow (NTDLL.@)
524 *
525 * Converts a large unsigned integer to an unicode string.
526 *
527 * Assigns a '\0' terminated wstring to str and returns str.
528 * Does not check if radix is in the range of 2 to 36 (as native DLL).
529 * For str == NULL just returns NULL (as native DLL).
530 *
531 * Difference:
532 * - This function does not exist in the native DLL (but in msvcrt).
533 * But since the maintenance of all these functions is better done
534 * in one place we implement it here.
535 */
536LPWSTR __cdecl _ui64tow( ULONGLONG value, LPWSTR str, INT radix )
537{
538 WCHAR buffer[65];
539 PWCHAR pos;
540 WCHAR digit;
541
542 pos = &buffer[64];
543 *pos = '\0';
544
545 do {
546 digit = value % radix;
547 value = value / radix;
548 if (digit < 10) {
549 *--pos = '0' + digit;
550 } else {
551 *--pos = 'a' + digit - 10;
552 } /* if */
553 } while (value != 0L);
554
555 if (str != NULL) {
556 memcpy(str, pos, (&buffer[64] - pos + 1) * sizeof(WCHAR));
557 } /* if */
558 return str;
559}
560
561
562/*********************************************************************
563 * _i64tow (NTDLL.@)
564 *
565 * Converts a large integer to an unicode string.
566 *
567 * Assigns a '\0' terminated wstring to str and returns str. If radix
568 * is 10 and value is negative, the value is converted with sign.
569 * Does not check if radix is in the range of 2 to 36 (as native DLL).
570 * For str == NULL just returns NULL (as native DLL).
571 *
572 * Difference:
573 * - The native DLL converts negative values (for base 10) wrong:
574 * -1 is converted to -18446744073709551615
575 * -2 is converted to -18446744073709551614
576 * -9223372036854775807 is converted to -9223372036854775809
577 * -9223372036854775808 is converted to -9223372036854775808
578 * The native msvcrt _i64tow function and our ntdll function do
579 * not have this bug.
580 */
581LPWSTR __cdecl _i64tow( LONGLONG value, LPWSTR str, INT radix )
582{
583 ULONGLONG val;
584 int negative;
585 WCHAR buffer[65];
586 PWCHAR pos;
587 WCHAR digit;
588
589 if (value < 0 && radix == 10) {
590 negative = 1;
591 val = -value;
592 } else {
593 negative = 0;
594 val = value;
595 } /* if */
596
597 pos = &buffer[64];
598 *pos = '\0';
599
600 do {
601 digit = val % radix;
602 val = val / radix;
603 if (digit < 10) {
604 *--pos = '0' + digit;
605 } else {
606 *--pos = 'a' + digit - 10;
607 } /* if */
608 } while (val != 0L);
609
610 if (negative) {
611 *--pos = '-';
612 } /* if */
613
614 if (str != NULL) {
615 memcpy(str, pos, (&buffer[64] - pos + 1) * sizeof(WCHAR));
616 } /* if */
617 return str;
618}
619
620
621/*********************************************************************
622 * _wtol (NTDLL.@)
623 *
624 * Converts an unicode string to a long integer.
625 *
626 * On success it returns the integer value otherwise it returns 0.
627 * Accepts: {whitespace} [+|-] {digits}
628 * No check of overflow: Just assigns lower 32 bits (as native DLL).
629 * Does not check for str != NULL (as native DLL).
630 */
631LONG __cdecl _wtol( LPWSTR str )
632{
633 ULONG RunningTotal = 0;
634 char bMinus = 0;
635
636 while (isspaceW(*str)) {
637 str++;
638 } /* while */
639
640 if (*str == '+') {
641 str++;
642 } else if (*str == '-') {
643 bMinus = 1;
644 str++;
645 } /* if */
646
647 while (*str >= '0' && *str <= '9') {
648 RunningTotal = RunningTotal * 10 + *str - '0';
649 str++;
650 } /* while */
651
652 return bMinus ? -RunningTotal : RunningTotal;
653}
654
655
656/*********************************************************************
657 * _wtoi (NTDLL.@)
658 *
659 * Converts an unicode string to an integer.
660 *
661 * On success it returns the integer value otherwise it returns 0.
662 * Accepts: {whitespace} [+|-] {digits}
663 * No check of overflow: Just assigns lower 32 bits (as native DLL).
664 * Does not check for str != NULL (as native DLL).
665 */
666int __cdecl _wtoi( LPWSTR string )
667{
668 return _wtol(string);
669}
670
671
672/*********************************************************************
673 * _wtoi64 (NTDLL.@)
674 *
675 * Converts an unicode string to a large integer.
676 *
677 * On success it returns the integer value otherwise it returns 0.
678 * Accepts: {whitespace} [+|-] {digits}
679 * No check of overflow: Just assigns lower 64 bits (as native DLL).
680 * Does not check for str != NULL (as native DLL).
681 */
682LONGLONG __cdecl _wtoi64( LPWSTR str )
683{
684 ULONGLONG RunningTotal = 0;
685 char bMinus = 0;
686
687 while (isspaceW(*str)) {
688 str++;
689 } /* while */
690
691 if (*str == '+') {
692 str++;
693 } else if (*str == '-') {
694 bMinus = 1;
695 str++;
696 } /* if */
697
698 while (*str >= '0' && *str <= '9') {
699 RunningTotal = RunningTotal * 10 + *str - '0';
700 str++;
701 } /* while */
702
703 return bMinus ? -RunningTotal : RunningTotal;
704}
705
706
707
708/***********************************************************************
709 * _snwprintf (NTDLL.@)
710 */
711int __cdecl NTDLL_snwprintf(WCHAR *str, unsigned int len, const WCHAR *format, ...)
712{
713 int retval;
714 va_list valist;
715 va_start(valist, format);
716 retval = vsnprintfW(str, len, format, valist);
717 va_end(valist);
718 return retval;
719}
720
721
722/***********************************************************************
723 * swprintf (NTDLL.@)
724 */
725int __cdecl NTDLL_swprintf(WCHAR *str, const WCHAR *format, ...)
726{
727 int retval;
728 va_list valist;
729 va_start(valist, format);
730 retval = vsnprintfW(str, INT_MAX, format, valist);
731 va_end(valist);
732 return retval;
733}
Note: See TracBrowser for help on using the repository browser.