Changeset 9986 for trunk/src/NTDLL/wcstring.c
- Timestamp:
- Apr 7, 2003, 8:40:53 PM (22 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/NTDLL/wcstring.c
r8429 r9986 4 4 * Copyright 2000 Alexandre Julliard 5 5 * Copyright 2000 Jon Griffiths 6 * Copyright 2003 Thomas Mertes 6 7 * 7 8 * This library is free software; you can redistribute it and/or … … 23 24 24 25 #include <ctype.h> 25 #include <limits.h>26 26 #include <stdlib.h> 27 27 #include <string.h> 28 28 #include <stdio.h> 29 30 #include "ntddk.h" 29 #include <limits.h> 30 31 #include "winternl.h" 31 32 #include "wine/unicode.h" 32 33 #include "wine/debug.h" … … 304 305 /********************************************************************* 305 306 * wcstol (NTDLL.@) 306 * Like strtol, but for wide character strings. 307 */ 308 INT __cdecl NTDLL_wcstol(LPCWSTR s,LPWSTR *end,INT base) 309 { 310 UNICODE_STRING uni; 311 ANSI_STRING ansi; 312 INT ret; 313 LPSTR endA; 314 315 RtlInitUnicodeString( &uni, s ); 316 RtlUnicodeStringToAnsiString( &ansi, &uni, TRUE ); 317 ret = strtol( ansi.Buffer, &endA, base ); 318 if (end) 319 { 320 DWORD len; 321 RtlMultiByteToUnicodeSize( &len, ansi.Buffer, endA - ansi.Buffer ); 322 *end = (LPWSTR)s + len/sizeof(WCHAR); 323 } 324 RtlFreeAnsiString( &ansi ); 325 return ret; 307 */ 308 long __cdecl NTDLL_wcstol(LPCWSTR s,LPWSTR *end,INT base) 309 { 310 return strtolW( s, end, base ); 326 311 } 327 312 … … 329 314 /********************************************************************* 330 315 * wcstoul (NTDLL.@) 331 * Like strtoul, but for wide character strings. 332 */ 333 INT __cdecl NTDLL_wcstoul(LPCWSTR s,LPWSTR *end,INT base) 334 { 335 UNICODE_STRING uni; 336 ANSI_STRING ansi; 337 INT ret; 338 LPSTR endA; 339 340 RtlInitUnicodeString( &uni, s ); 341 RtlUnicodeStringToAnsiString( &ansi, &uni, TRUE ); 342 ret = strtoul( ansi.Buffer, &endA, base ); 343 if (end) 344 { 345 DWORD len; 346 RtlMultiByteToUnicodeSize( &len, ansi.Buffer, endA - ansi.Buffer ); 347 *end = (LPWSTR)s + len/sizeof(WCHAR); 348 } 349 RtlFreeAnsiString( &ansi ); 350 return ret; 316 */ 317 unsigned long __cdecl NTDLL_wcstoul(LPCWSTR s,LPWSTR *end,INT base) 318 { 319 return strtoulW( s, end, base ); 351 320 } 352 321 … … 369 338 } 370 339 371 372 /********************************************************************* 373 * _ultow (NTDLL.@) 374 * Like _ultoa, but for wide character strings. 375 */ 376 LPWSTR __cdecl _ultow(ULONG value, LPWSTR string, INT radix) 377 { 378 WCHAR tmp[33]; 379 LPWSTR tp = tmp; 380 LPWSTR sp; 381 LONG i; 382 ULONG v = value; 383 384 if (radix > 36 || radix <= 1) 385 return 0; 386 387 while (v || tp == tmp) 388 { 389 i = v % radix; 390 v = v / radix; 391 if (i < 10) 392 *tp++ = i + '0'; 393 else 394 *tp++ = i + 'a' - 10; 395 } 396 397 sp = string; 398 while (tp > tmp) 399 *sp++ = *--tp; 400 *sp = 0; 401 return string; 402 } 403 404 /********************************************************************* 405 * _wtol (NTDLL.@) 406 * Like atol, but for wide character strings. 407 */ 408 LONG __cdecl _wtol(LPWSTR string) 409 { 410 char buffer[30]; 411 NTDLL_wcstombs( buffer, string, sizeof(buffer) ); 412 return atol( buffer ); 413 } 414 415 /********************************************************************* 416 * _wtoi (NTDLL.@) 417 */ 418 INT __cdecl _wtoi(LPWSTR string) 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 */ 349 INT __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 */ 364 INT __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 */ 379 INT __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 */ 394 INT __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 */ 409 LPWSTR __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 */ 450 LPWSTR __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 */ 513 LPWSTR __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 */ 536 LPWSTR __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 */ 581 LPWSTR __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 */ 631 LONG __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 */ 666 int __cdecl _wtoi( LPWSTR string ) 419 667 { 420 668 return _wtol(string); 421 669 } 422 670 423 /* INTERNAL: Wide char snprintf 424 * If you fix a bug in this function, fix it in msvcrt/wcs.c also! 425 */ 426 static int __cdecl NTDLL_vsnwprintf(WCHAR *str, unsigned int len, 427 const WCHAR *format, va_list valist) 428 { 429 unsigned int written = 0; 430 const WCHAR *iter = format; 431 char bufa[256], fmtbufa[64], *fmta; 432 433 TRACE("(%d,%s)\n",len,debugstr_w(format)); 434 435 while (*iter) 436 { 437 while (*iter && *iter != (WCHAR)L'%') 438 { 439 if (written++ >= len) 440 return -1; 441 *str++ = *iter++; 442 } 443 if (*iter == (WCHAR)L'%') 444 { 445 fmta = fmtbufa; 446 *fmta++ = *iter++; 447 while (*iter == (WCHAR)L'0' || 448 *iter == (WCHAR)L'+' || 449 *iter == (WCHAR)L'-' || 450 *iter == (WCHAR)L' ' || 451 *iter == (WCHAR)L'0' || 452 *iter == (WCHAR)L'*' || 453 *iter == (WCHAR)L'#') 454 { 455 if (*iter == (WCHAR)L'*') 456 { 457 char *buffiter = bufa; 458 int fieldlen = va_arg(valist, int); 459 sprintf(buffiter, "%d", fieldlen); 460 while (*buffiter) 461 *fmta++ = *buffiter++; 462 } 463 else 464 *fmta++ = *iter; 465 iter++; 466 } 467 468 while (isdigit(*iter)) 469 *fmta++ = *iter++; 470 471 if (*iter == (WCHAR)L'.') 472 { 473 *fmta++ = *iter++; 474 if (*iter == (WCHAR)L'*') 475 { 476 char *buffiter = bufa; 477 int fieldlen = va_arg(valist, int); 478 sprintf(buffiter, "%d", fieldlen); 479 while (*buffiter) 480 *fmta++ = *buffiter++; 481 } 482 else 483 while (isdigit(*iter)) 484 *fmta++ = *iter++; 485 } 486 if (*iter == (WCHAR)L'h' || 487 *iter == (WCHAR)L'l') 488 { 489 *fmta++ = *iter++; 490 *fmta++ = *iter++; 491 } 492 493 switch (*iter) 494 { 495 case (WCHAR)L's': 496 { 497 static const WCHAR none[] = { '(', 'n', 'u', 'l', 'l', ')', 0 }; 498 const WCHAR *wstr = va_arg(valist, const WCHAR *); 499 const WCHAR *striter = wstr ? wstr : none; 500 while (*striter) 501 { 502 if (written++ >= len) 503 return -1; 504 *str++ = *striter++; 505 } 506 iter++; 507 break; 508 } 509 510 case (WCHAR)L'c': 511 if (written++ >= len) 512 return -1; 513 *str++ = (WCHAR)va_arg(valist, int); 514 iter++; 515 break; 516 517 default: 518 { 519 /* For non wc types, use system sprintf and append to wide char output */ 520 /* FIXME: for unrecognised types, should ignore % when printing */ 521 char *bufaiter = bufa; 522 if (*iter == (WCHAR)L'p') 523 sprintf(bufaiter, "%08lX", va_arg(valist, long)); 524 else 525 { 526 *fmta++ = *iter; 527 *fmta = '\0'; 528 if (*iter == (WCHAR)L'f') 529 sprintf(bufaiter, fmtbufa, va_arg(valist, double)); 530 else 531 sprintf(bufaiter, fmtbufa, va_arg(valist, void *)); 532 } 533 while (*bufaiter) 534 { 535 if (written++ >= len) 536 return -1; 537 *str++ = *bufaiter++; 538 } 539 iter++; 540 break; 541 } 542 } 543 } 544 } 545 if (written >= len) 546 return -1; 547 *str++ = (WCHAR)L'\0'; 548 return (int)written; 549 } 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 */ 682 LONGLONG __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 550 706 551 707 … … 558 714 va_list valist; 559 715 va_start(valist, format); 560 retval = NTDLL_vsnwprintf(str, len, format, valist);716 retval = vsnprintfW(str, len, format, valist); 561 717 va_end(valist); 562 718 return retval; … … 572 728 va_list valist; 573 729 va_start(valist, format); 574 retval = NTDLL_vsnwprintf(str, INT_MAX, format, valist);730 retval = vsnprintfW(str, INT_MAX, format, valist); 575 731 va_end(valist); 576 732 return retval;
Note:
See TracChangeset
for help on using the changeset viewer.