Implement _itoa, _ltoa, _ultoa, _i64toa, _ui64toa, _itow, _ltow,

_ultow, _i64tow, _ui64tow, _atoi64, _wtoi, _wtol, _wtoi64.
This commit is contained in:
Thomas Mertes 2003-03-12 20:16:07 +00:00 committed by Alexandre Julliard
parent 585e9d6c24
commit 414772ac28
3 changed files with 491 additions and 60 deletions

View File

@ -889,14 +889,18 @@
@ stdcall -ret64 _allmul(long long long long) _allmul @ stdcall -ret64 _allmul(long long long long) _allmul
@ stdcall -register -i386 _alloca_probe() NTDLL_alloca_probe @ stdcall -register -i386 _alloca_probe() NTDLL_alloca_probe
@ stdcall -ret64 _allrem(long long long long) _allrem @ stdcall -ret64 _allrem(long long long long) _allrem
@ cdecl -ret64 _atoi64(str) _atoi64
@ stdcall -ret64 _aulldiv(long long long long) _aulldiv @ stdcall -ret64 _aulldiv(long long long long) _aulldiv
@ stdcall -ret64 _aullrem(long long long long) _aullrem @ stdcall -ret64 _aullrem(long long long long) _aullrem
@ stdcall -register -i386 _chkstk() NTDLL_chkstk @ stdcall -register -i386 _chkstk() NTDLL_chkstk
@ stub _fltused @ stub _fltused
@ cdecl _ftol() NTDLL__ftol @ cdecl _ftol() NTDLL__ftol
@ cdecl _i64toa(long long ptr long) _i64toa
@ cdecl _i64tow(long long ptr long) _i64tow
@ cdecl _itoa(long ptr long) _itoa @ cdecl _itoa(long ptr long) _itoa
@ stub _itow #(long ptr long) _itow @ cdecl _itow(long ptr long) _itow
@ cdecl _ltoa(long ptr long) _ltoa @ cdecl _ltoa(long ptr long) _ltoa
@ cdecl _ltow(long ptr long) _ltow
@ cdecl _memccpy(ptr ptr long long) memccpy @ cdecl _memccpy(ptr ptr long long) memccpy
@ cdecl _memicmp(str str long) NTDLL__memicmp @ cdecl _memicmp(str str long) NTDLL__memicmp
@ varargs _snprintf(ptr long ptr) snprintf @ varargs _snprintf(ptr long ptr) snprintf
@ -907,6 +911,8 @@
@ cdecl _strlwr(str) _strlwr @ cdecl _strlwr(str) _strlwr
@ cdecl _strnicmp(str str long) strncasecmp @ cdecl _strnicmp(str str long) strncasecmp
@ cdecl _strupr(str) _strupr @ cdecl _strupr(str) _strupr
@ cdecl _ui64toa(long long ptr long) _ui64toa
@ cdecl _ui64tow(long long ptr long) _ui64tow
@ cdecl _ultoa(long ptr long) _ultoa @ cdecl _ultoa(long ptr long) _ultoa
@ cdecl _ultow(long ptr long) _ultow @ cdecl _ultow(long ptr long) _ultow
@ cdecl _vsnprintf(ptr long ptr ptr) vsnprintf @ cdecl _vsnprintf(ptr long ptr ptr) vsnprintf
@ -914,8 +920,9 @@
@ cdecl _wcslwr(wstr) NTDLL__wcslwr @ cdecl _wcslwr(wstr) NTDLL__wcslwr
@ cdecl _wcsnicmp(wstr wstr long) NTDLL__wcsnicmp @ cdecl _wcsnicmp(wstr wstr long) NTDLL__wcsnicmp
@ cdecl _wcsupr(wstr) NTDLL__wcsupr @ cdecl _wcsupr(wstr) NTDLL__wcsupr
@ cdecl _wtoi(wstr) NTDLL__wtoi @ cdecl _wtoi(wstr) _wtoi
@ cdecl _wtol(wstr) NTDLL__wtol @ cdecl _wtoi64(wstr) _wtoi64
@ cdecl _wtol(wstr) _wtol
@ cdecl abs(long) abs @ cdecl abs(long) abs
@ cdecl atan(double) atan @ cdecl atan(double) atan
@ cdecl atoi(str) atoi @ cdecl atoi(str) atoi

View File

@ -3,6 +3,7 @@
* *
* Copyright 2000 Alexandre Julliard * Copyright 2000 Alexandre Julliard
* Copyright 2000 Jon Griffiths * Copyright 2000 Jon Griffiths
* Copyright 2003 Thomas Mertes
* *
* This library is free software; you can redistribute it and/or * This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public * modify it under the terms of the GNU Lesser General Public
@ -25,6 +26,8 @@
#include <string.h> #include <string.h>
#include "windef.h" #include "windef.h"
#include "winternl.h"
/********************************************************************* /*********************************************************************
* _memicmp (NTDLL.@) * _memicmp (NTDLL.@)
@ -41,6 +44,7 @@ INT __cdecl NTDLL__memicmp( LPCSTR s1, LPCSTR s2, DWORD len )
return ret; return ret;
} }
/********************************************************************* /*********************************************************************
* _strupr (NTDLL.@) * _strupr (NTDLL.@)
*/ */
@ -51,6 +55,7 @@ LPSTR __cdecl _strupr( LPSTR str )
return ret; return ret;
} }
/********************************************************************* /*********************************************************************
* _strlwr (NTDLL.@) * _strlwr (NTDLL.@)
* *
@ -66,46 +71,223 @@ LPSTR __cdecl _strlwr( LPSTR str )
/********************************************************************* /*********************************************************************
* _ultoa (NTDLL.@) * _ultoa (NTDLL.@)
*
* Converts an unsigned long integer to a string.
*
* Assigns a '\0' terminated string to str and returns str.
* Does not check if radix is in the range of 2 to 36 (as native DLL).
* For str == NULL just crashes (as native DLL).
*/ */
LPSTR __cdecl _ultoa( unsigned long x, LPSTR buf, INT radix ) char * __cdecl _ultoa( unsigned long value, char *str, int radix )
{ {
char *p, buffer[8*sizeof(unsigned long) + 1]; /* assume 8-bit chars */ char buffer[33];
char *pos;
int digit;
p = buffer + sizeof(buffer); pos = &buffer[32];
*--p = 0; *pos = '\0';
do
{ do {
int rem = x % radix; digit = value % radix;
*--p = (rem <= 9) ? rem + '0' : rem + 'a' - 10; value = value / radix;
x /= radix; if (digit < 10) {
} while (x); *--pos = '0' + digit;
strcpy( buf, p ); } else {
return buf; *--pos = 'a' + digit - 10;
} /* if */
} while (value != 0L);
memcpy(str, pos, &buffer[32] - pos + 1);
return str;
} }
/********************************************************************* /*********************************************************************
* _ltoa (NTDLL.@) * _ltoa (NTDLL.@)
*
* Converts a long integer to a string.
*
* Assigns a '\0' terminated string to str and returns str. If radix
* is 10 and value is negative, the value is converted with sign.
* Does not check if radix is in the range of 2 to 36 (as native DLL).
* For str == NULL just crashes (as native DLL).
*/ */
LPSTR __cdecl _ltoa( long x, LPSTR buf, INT radix ) char * __cdecl _ltoa( long value, char *str, int radix )
{ {
LPSTR p = buf; unsigned long val;
if (x < 0) int negative;
{ char buffer[33];
*p++ = '-'; char *pos;
x = -x; int digit;
}
_ultoa( x, p, radix ); if (value < 0 && radix == 10) {
return buf; negative = 1;
val = -value;
} else {
negative = 0;
val = value;
} /* if */
pos = &buffer[32];
*pos = '\0';
do {
digit = val % radix;
val = val / radix;
if (digit < 10) {
*--pos = '0' + digit;
} else {
*--pos = 'a' + digit - 10;
} /* if */
} while (val != 0L);
if (negative) {
*--pos = '-';
} /* if */
memcpy(str, pos, &buffer[32] - pos + 1);
return str;
} }
/********************************************************************* /*********************************************************************
* _itoa (NTDLL.@) * _itoa (NTDLL.@)
*
* Converts an integer to a string.
*
* Assigns a '\0' terminated wstring to str and returns str. If radix
* is 10 and value is negative, the value is converted with sign.
* Does not check if radix is in the range of 2 to 36 (as native DLL).
* For str == NULL just crashes (as native DLL).
*/ */
LPSTR __cdecl _itoa( int x, LPSTR buf, INT radix ) char * __cdecl _itoa( int value, char *str, int radix )
{ {
return _ltoa( x, buf, radix ); return _ltoa(value, str, radix);
}
/*********************************************************************
* _ui64toa (NTDLL.@)
*
* Converts a large unsigned integer to a string.
*
* Assigns a '\0' terminated string to str and returns str.
* Does not check if radix is in the range of 2 to 36 (as native DLL).
* For str == NULL just crashes (as native DLL).
*/
char * __cdecl _ui64toa( ULONGLONG value, char *str, int radix )
{
char buffer[65];
char *pos;
int digit;
pos = &buffer[64];
*pos = '\0';
do {
digit = value % radix;
value = value / radix;
if (digit < 10) {
*--pos = '0' + digit;
} else {
*--pos = 'a' + digit - 10;
} /* if */
} while (value != 0L);
memcpy(str, pos, &buffer[64] - pos + 1);
return str;
}
/*********************************************************************
* _i64toa (NTDLL.@)
*
* Converts a large integer to a string.
*
* Assigns a '\0' terminated string to str and returns str. If radix
* is 10 and value is negative, the value is converted with sign.
* Does not check if radix is in the range of 2 to 36 (as native DLL).
* For str == NULL just crashes (as native DLL).
*
* Difference:
* - The native DLL converts negative values (for base 10) wrong:
* -1 is converted to -18446744073709551615
* -2 is converted to -18446744073709551614
* -9223372036854775807 is converted to -9223372036854775809
* -9223372036854775808 is converted to -9223372036854775808
* The native msvcrt _i64toa function and our ntdll function do
* not have this bug.
*/
char * __cdecl _i64toa( LONGLONG value, char *str, int radix )
{
ULONGLONG val;
int negative;
char buffer[65];
char *pos;
int digit;
if (value < 0 && radix == 10) {
negative = 1;
val = -value;
} else {
negative = 0;
val = value;
} /* if */
pos = &buffer[64];
*pos = '\0';
do {
digit = val % radix;
val = val / radix;
if (digit < 10) {
*--pos = '0' + digit;
} else {
*--pos = 'a' + digit - 10;
} /* if */
} while (val != 0L);
if (negative) {
*--pos = '-';
} /* if */
memcpy(str, pos, &buffer[64] - pos + 1);
return str;
}
/*********************************************************************
* _atoi64 (NTDLL.@)
*
* Converts a string to a large integer.
*
* On success it returns the integer value otherwise it returns 0.
* Accepts: {whitespace} [+|-] {digits}
* No check of overflow: Just assigns lower 64 bits (as native DLL).
* Does not check for str != NULL (as native DLL).
*/
LONGLONG __cdecl _atoi64( char *str )
{
ULONGLONG RunningTotal = 0;
char bMinus = 0;
while (*str == ' ' || (*str >= '\011' && *str <= '\015')) {
str++;
} /* while */
if (*str == '+') {
str++;
} else if (*str == '-') {
bMinus = 1;
str++;
} /* if */
while (*str >= '0' && *str <= '9') {
RunningTotal = RunningTotal * 10 + *str - '0';
str++;
} /* while */
return bMinus ? -RunningTotal : RunningTotal;
} }

View File

@ -3,6 +3,7 @@
* *
* Copyright 2000 Alexandre Julliard * Copyright 2000 Alexandre Julliard
* Copyright 2000 Jon Griffiths * Copyright 2000 Jon Griffiths
* Copyright 2003 Thomas Mertes
* *
* This library is free software; you can redistribute it and/or * This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public * modify it under the terms of the GNU Lesser General Public
@ -339,53 +340,294 @@ INT __cdecl NTDLL_iswalpha( WCHAR wc )
/********************************************************************* /*********************************************************************
* _ultow (NTDLL.@) * _ultow (NTDLL.@)
* Like _ultoa, but for wide character strings. *
* Converts an unsigned long integer to an unicode string.
*
* Assigns a '\0' terminated string to str and returns str.
* Does not check if radix is in the range of 2 to 36 (as native DLL).
* For str == NULL just returns NULL (as native DLL).
*/ */
LPWSTR __cdecl _ultow(ULONG value, LPWSTR string, INT radix) LPWSTR __cdecl _ultow( unsigned long value, LPWSTR str, INT radix )
{ {
WCHAR tmp[33]; WCHAR buffer[33];
LPWSTR tp = tmp; PWCHAR pos;
LPWSTR sp; WCHAR digit;
LONG i;
ULONG v = value;
if (radix > 36 || radix <= 1) pos = &buffer[32];
return 0; *pos = '\0';
while (v || tp == tmp) do {
{ digit = value % radix;
i = v % radix; value = value / radix;
v = v / radix; if (digit < 10) {
if (i < 10) *--pos = '0' + digit;
*tp++ = i + '0'; } else {
else *--pos = 'a' + digit - 10;
*tp++ = i + 'a' - 10; } /* if */
} while (value != 0L);
if (str != NULL) {
memcpy(str, pos, (&buffer[32] - pos + 1) * sizeof(WCHAR));
} /* if */
return str;
} }
sp = string;
while (tp > tmp) /*********************************************************************
*sp++ = *--tp; * _ltow (NTDLL.@)
*sp = 0; *
return string; * Converts a long integer to an unicode string.
*
* Assigns a '\0' terminated string to str and returns str. If radix
* is 10 and value is negative, the value is converted with sign.
* Does not check if radix is in the range of 2 to 36 (as native DLL).
* For str == NULL just returns NULL (as native DLL).
*/
LPWSTR __cdecl _ltow( long value, LPWSTR str, INT radix )
{
unsigned long val;
int negative;
WCHAR buffer[33];
PWCHAR pos;
WCHAR digit;
if (value < 0 && radix == 10) {
negative = 1;
val = -value;
} else {
negative = 0;
val = value;
} /* if */
pos = &buffer[32];
*pos = '\0';
do {
digit = val % radix;
val = val / radix;
if (digit < 10) {
*--pos = '0' + digit;
} else {
*--pos = 'a' + digit - 10;
} /* if */
} while (val != 0L);
if (negative) {
*--pos = '-';
} /* if */
if (str != NULL) {
memcpy(str, pos, (&buffer[32] - pos + 1) * sizeof(WCHAR));
} /* if */
return str;
} }
/*********************************************************************
* _itow (NTDLL.@)
*
* Converts an integer to an unicode string.
*
* Assigns a '\0' terminated wstring to str and returns str. If radix
* is 10 and value is negative, the value is converted with sign.
* Does not check if radix is in the range of 2 to 36 (as native DLL).
* For str == NULL just returns NULL (as native DLL).
*
* Difference:
* - The native DLL crashes when the string is longer than 19 chars.
* This function does not have this bug.
*/
LPWSTR __cdecl _itow( int value, LPWSTR str, INT radix )
{
return _ltow(value, str, radix);
}
/*********************************************************************
* _ui64tow (NTDLL.@)
*
* Converts a large unsigned integer to an unicode string.
*
* Assigns a '\0' terminated wstring to str and returns str.
* Does not check if radix is in the range of 2 to 36 (as native DLL).
* For str == NULL just returns NULL (as native DLL).
*
* Difference:
* - This function does not exist in the native DLL (but in msvcrt).
* But since the maintenance of all these functions is better done
* in one place we implement it here.
*/
LPWSTR __cdecl _ui64tow( ULONGLONG value, LPWSTR str, INT radix )
{
WCHAR buffer[65];
PWCHAR pos;
WCHAR digit;
pos = &buffer[64];
*pos = '\0';
do {
digit = value % radix;
value = value / radix;
if (digit < 10) {
*--pos = '0' + digit;
} else {
*--pos = 'a' + digit - 10;
} /* if */
} while (value != 0L);
if (str != NULL) {
memcpy(str, pos, (&buffer[64] - pos + 1) * sizeof(WCHAR));
} /* if */
return str;
}
/*********************************************************************
* _i64tow (NTDLL.@)
*
* Converts a large integer to an unicode string.
*
* Assigns a '\0' terminated wstring to str and returns str. If radix
* is 10 and value is negative, the value is converted with sign.
* Does not check if radix is in the range of 2 to 36 (as native DLL).
* For str == NULL just returns NULL (as native DLL).
*
* Difference:
* - The native DLL converts negative values (for base 10) wrong:
* -1 is converted to -18446744073709551615
* -2 is converted to -18446744073709551614
* -9223372036854775807 is converted to -9223372036854775809
* -9223372036854775808 is converted to -9223372036854775808
* The native msvcrt _i64tow function and our ntdll function do
* not have this bug.
*/
LPWSTR __cdecl _i64tow( LONGLONG value, LPWSTR str, INT radix )
{
ULONGLONG val;
int negative;
WCHAR buffer[65];
PWCHAR pos;
WCHAR digit;
if (value < 0 && radix == 10) {
negative = 1;
val = -value;
} else {
negative = 0;
val = value;
} /* if */
pos = &buffer[64];
*pos = '\0';
do {
digit = val % radix;
val = val / radix;
if (digit < 10) {
*--pos = '0' + digit;
} else {
*--pos = 'a' + digit - 10;
} /* if */
} while (val != 0L);
if (negative) {
*--pos = '-';
} /* if */
if (str != NULL) {
memcpy(str, pos, (&buffer[64] - pos + 1) * sizeof(WCHAR));
} /* if */
return str;
}
/********************************************************************* /*********************************************************************
* _wtol (NTDLL.@) * _wtol (NTDLL.@)
* Like atol, but for wide character strings. *
* Converts an unicode string to a long integer.
*
* On success it returns the integer value otherwise it returns 0.
* Accepts: {whitespace} [+|-] {digits}
* No check of overflow: Just assigns lower 32 bits (as native DLL).
* Does not check for str != NULL (as native DLL).
*/ */
LONG __cdecl NTDLL__wtol(LPWSTR string) LONG __cdecl _wtol( LPWSTR str )
{ {
return strtolW( string, NULL, 10 ); ULONG RunningTotal = 0;
char bMinus = 0;
while (isspaceW(*str)) {
str++;
} /* while */
if (*str == '+') {
str++;
} else if (*str == '-') {
bMinus = 1;
str++;
} /* if */
while (*str >= '0' && *str <= '9') {
RunningTotal = RunningTotal * 10 + *str - '0';
str++;
} /* while */
return bMinus ? -RunningTotal : RunningTotal;
} }
/********************************************************************* /*********************************************************************
* _wtoi (NTDLL.@) * _wtoi (NTDLL.@)
*
* Converts an unicode string to an integer.
*
* On success it returns the integer value otherwise it returns 0.
* Accepts: {whitespace} [+|-] {digits}
* No check of overflow: Just assigns lower 32 bits (as native DLL).
* Does not check for str != NULL (as native DLL).
*/ */
INT __cdecl NTDLL__wtoi(LPWSTR string) int __cdecl _wtoi( LPWSTR string )
{ {
return NTDLL__wtol(string); return _wtol(string);
} }
/*********************************************************************
* _wtoi64 (NTDLL.@)
*
* Converts an unicode string to a large integer.
*
* On success it returns the integer value otherwise it returns 0.
* Accepts: {whitespace} [+|-] {digits}
* No check of overflow: Just assigns lower 64 bits (as native DLL).
* Does not check for str != NULL (as native DLL).
*/
LONGLONG __cdecl _wtoi64( LPWSTR str )
{
ULONGLONG RunningTotal = 0;
char bMinus = 0;
while (isspaceW(*str)) {
str++;
} /* while */
if (*str == '+') {
str++;
} else if (*str == '-') {
bMinus = 1;
str++;
} /* if */
while (*str >= '0' && *str <= '9') {
RunningTotal = RunningTotal * 10 + *str - '0';
str++;
} /* while */
return bMinus ? -RunningTotal : RunningTotal;
}
/* INTERNAL: Wide char snprintf /* INTERNAL: Wide char snprintf
* If you fix a bug in this function, fix it in msvcrt/wcs.c also! * If you fix a bug in this function, fix it in msvcrt/wcs.c also!
*/ */