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 -register -i386 _alloca_probe() NTDLL_alloca_probe
@ stdcall -ret64 _allrem(long long long long) _allrem
@ cdecl -ret64 _atoi64(str) _atoi64
@ stdcall -ret64 _aulldiv(long long long long) _aulldiv
@ stdcall -ret64 _aullrem(long long long long) _aullrem
@ stdcall -register -i386 _chkstk() NTDLL_chkstk
@ stub _fltused
@ cdecl _ftol() NTDLL__ftol
@ cdecl _i64toa(long long ptr long) _i64toa
@ cdecl _i64tow(long long ptr long) _i64tow
@ 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 _ltow(long ptr long) _ltow
@ cdecl _memccpy(ptr ptr long long) memccpy
@ cdecl _memicmp(str str long) NTDLL__memicmp
@ varargs _snprintf(ptr long ptr) snprintf
@ -907,6 +911,8 @@
@ cdecl _strlwr(str) _strlwr
@ cdecl _strnicmp(str str long) strncasecmp
@ 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 _ultow(long ptr long) _ultow
@ cdecl _vsnprintf(ptr long ptr ptr) vsnprintf
@ -914,8 +920,9 @@
@ cdecl _wcslwr(wstr) NTDLL__wcslwr
@ cdecl _wcsnicmp(wstr wstr long) NTDLL__wcsnicmp
@ cdecl _wcsupr(wstr) NTDLL__wcsupr
@ cdecl _wtoi(wstr) NTDLL__wtoi
@ cdecl _wtol(wstr) NTDLL__wtol
@ cdecl _wtoi(wstr) _wtoi
@ cdecl _wtoi64(wstr) _wtoi64
@ cdecl _wtol(wstr) _wtol
@ cdecl abs(long) abs
@ cdecl atan(double) atan
@ cdecl atoi(str) atoi

View File

@ -3,6 +3,7 @@
*
* Copyright 2000 Alexandre Julliard
* Copyright 2000 Jon Griffiths
* Copyright 2003 Thomas Mertes
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@ -25,6 +26,8 @@
#include <string.h>
#include "windef.h"
#include "winternl.h"
/*********************************************************************
* _memicmp (NTDLL.@)
@ -41,6 +44,7 @@ INT __cdecl NTDLL__memicmp( LPCSTR s1, LPCSTR s2, DWORD len )
return ret;
}
/*********************************************************************
* _strupr (NTDLL.@)
*/
@ -51,6 +55,7 @@ LPSTR __cdecl _strupr( LPSTR str )
return ret;
}
/*********************************************************************
* _strlwr (NTDLL.@)
*
@ -66,46 +71,223 @@ LPSTR __cdecl _strlwr( LPSTR str )
/*********************************************************************
* _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);
*--p = 0;
do
{
int rem = x % radix;
*--p = (rem <= 9) ? rem + '0' : rem + 'a' - 10;
x /= radix;
} while (x);
strcpy( buf, p );
return buf;
pos = &buffer[32];
*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[32] - pos + 1);
return str;
}
/*********************************************************************
* _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;
if (x < 0)
{
*p++ = '-';
x = -x;
}
_ultoa( x, p, radix );
return buf;
unsigned long val;
int negative;
char buffer[33];
char *pos;
int 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 */
memcpy(str, pos, &buffer[32] - pos + 1);
return str;
}
/*********************************************************************
* _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 Jon Griffiths
* Copyright 2003 Thomas Mertes
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@ -339,53 +340,294 @@ INT __cdecl NTDLL_iswalpha( WCHAR wc )
/*********************************************************************
* _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];
LPWSTR tp = tmp;
LPWSTR sp;
LONG i;
ULONG v = value;
WCHAR buffer[33];
PWCHAR pos;
WCHAR digit;
if (radix > 36 || radix <= 1)
return 0;
pos = &buffer[32];
*pos = '\0';
while (v || tp == tmp)
{
i = v % radix;
v = v / radix;
if (i < 10)
*tp++ = i + '0';
else
*tp++ = i + 'a' - 10;
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[32] - pos + 1) * sizeof(WCHAR));
} /* if */
return str;
}
sp = string;
while (tp > tmp)
*sp++ = *--tp;
*sp = 0;
return string;
/*********************************************************************
* _ltow (NTDLL.@)
*
* 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.@)
* 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.@)
*
* 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
* If you fix a bug in this function, fix it in msvcrt/wcs.c also!
*/