Implemented strtolW/strtoulW in libwine_unicode and used it to replace

wcstol and friends.
This commit is contained in:
Alexandre Julliard 2002-05-16 18:58:47 +00:00
parent 1f18f61bfa
commit 9b6f433ebb
13 changed files with 273 additions and 61 deletions

View File

@ -67,8 +67,6 @@ typedef struct _LOADDATA
typedef HRESULT (CALLBACK *DPALOADPROC)(LPLOADDATA,IStream*,LPARAM); typedef HRESULT (CALLBACK *DPALOADPROC)(LPLOADDATA,IStream*,LPARAM);
INT __cdecl _wtoi(LPWSTR string);
/************************************************************************** /**************************************************************************
* DPA_LoadStream [COMCTL32.9] * DPA_LoadStream [COMCTL32.9]
* *
@ -2483,7 +2481,7 @@ COMCTL32_StrToIntA (LPSTR lpString)
INT WINAPI INT WINAPI
COMCTL32_StrToIntW (LPWSTR lpString) COMCTL32_StrToIntW (LPWSTR lpString)
{ {
return _wtoi(lpString); return atoiW(lpString);
} }

View File

@ -31,6 +31,7 @@
#include "ntddk.h" #include "ntddk.h"
#include "winbase.h" #include "winbase.h"
#include "commctrl.h" #include "commctrl.h"
#include "wine/unicode.h"
#include "wine/debug.h" #include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(ipaddress); WINE_DEFAULT_DEBUG_CHANNEL(ipaddress);
@ -237,7 +238,7 @@ static int IPADDRESS_GetAddress (IPADDRESS_INFO *infoPtr, LPDWORD ip_address)
for (i = 0; i < 4; i++) { for (i = 0; i < 4; i++) {
ip_addr *= 256; ip_addr *= 256;
if (GetWindowTextW (infoPtr->Part[i].EditHwnd, field, 4)) if (GetWindowTextW (infoPtr->Part[i].EditHwnd, field, 4))
ip_addr += wcstol(field, 0, 10); ip_addr += atolW(field);
else else
invalid++; invalid++;
} }
@ -320,7 +321,7 @@ static BOOL IPADDRESS_ConstrainField (IPADDRESS_INFO *infoPtr, int currentfield)
if (!GetWindowTextW (part->EditHwnd, field, 4)) return FALSE; if (!GetWindowTextW (part->EditHwnd, field, 4)) return FALSE;
curValue = wcstol(field, 0, 10); curValue = atoiW(field);
TRACE(" curValue=%d\n", curValue); TRACE(" curValue=%d\n", curValue);
newValue = IPADDRESS_IPNotify(infoPtr, currentfield, curValue); newValue = IPADDRESS_IPNotify(infoPtr, currentfield, curValue);

View File

@ -30,6 +30,7 @@
#include "commctrl.h" #include "commctrl.h"
#include "winnls.h" #include "winnls.h"
#include "ntddk.h" #include "ntddk.h"
#include "wine/unicode.h"
#include "wine/debug.h" #include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(updown); WINE_DEFAULT_DEBUG_CHANNEL(updown);
@ -275,7 +276,7 @@ static BOOL UPDOWN_GetBuddyInt (UPDOWN_INFO *infoPtr)
*dst = 0; *dst = 0;
/* try to convert the number and validate it */ /* try to convert the number and validate it */
newVal = wcstol(txt, &src, infoPtr->Base); newVal = strtolW(txt, &src, infoPtr->Base);
if(*src || !UPDOWN_InBounds (infoPtr, newVal)) return FALSE; if(*src || !UPDOWN_InBounds (infoPtr, newVal)) return FALSE;
} }

View File

@ -884,7 +884,7 @@ name ntdll
@ cdecl _itoa(long ptr long) _itoa @ cdecl _itoa(long ptr long) _itoa
@ cdecl _ltoa(long ptr long) _ltoa @ cdecl _ltoa(long ptr long) _ltoa
@ cdecl _memccpy(ptr ptr long long) memccpy @ cdecl _memccpy(ptr ptr long long) memccpy
@ cdecl _memicmp(str str long) _memicmp @ cdecl _memicmp(str str long) NTDLL__memicmp
@ varargs _snprintf(ptr long ptr) snprintf @ varargs _snprintf(ptr long ptr) snprintf
@ varargs _snwprintf(wstr long wstr) _snwprintf @ varargs _snwprintf(wstr long wstr) _snwprintf
@ cdecl _splitpath(str ptr ptr ptr ptr) _splitpath @ cdecl _splitpath(str ptr ptr ptr ptr) _splitpath
@ -900,8 +900,8 @@ name ntdll
@ 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) _wtoi @ cdecl _wtoi(wstr) NTDLL__wtoi
@ cdecl _wtol(wstr) _wtol @ cdecl _wtol(wstr) NTDLL__wtol
@ cdecl -noimport abs(long) abs @ cdecl -noimport abs(long) abs
@ cdecl -noimport atan(double) atan @ cdecl -noimport atan(double) atan
@ cdecl -noimport atoi(str) atoi @ cdecl -noimport atoi(str) atoi

View File

@ -29,7 +29,7 @@
/********************************************************************* /*********************************************************************
* _memicmp (NTDLL.@) * _memicmp (NTDLL.@)
*/ */
INT __cdecl _memicmp( LPCSTR s1, LPCSTR s2, DWORD len ) INT __cdecl NTDLL__memicmp( LPCSTR s1, LPCSTR s2, DWORD len )
{ {
int ret = 0; int ret = 0;
while (len--) while (len--)

View File

@ -303,51 +303,19 @@ INT __cdecl NTDLL_mbstowcs( LPWSTR dst, LPCSTR src, INT n )
/********************************************************************* /*********************************************************************
* wcstol (NTDLL.@) * wcstol (NTDLL.@)
* Like strtol, but for wide character strings.
*/ */
INT __cdecl NTDLL_wcstol(LPCWSTR s,LPWSTR *end,INT base) long __cdecl NTDLL_wcstol(LPCWSTR s,LPWSTR *end,INT base)
{ {
UNICODE_STRING uni; return strtolW( s, end, base );
ANSI_STRING ansi;
INT ret;
LPSTR endA;
RtlInitUnicodeString( &uni, s );
RtlUnicodeStringToAnsiString( &ansi, &uni, TRUE );
ret = strtol( ansi.Buffer, &endA, base );
if (end)
{
DWORD len;
RtlMultiByteToUnicodeSize( &len, ansi.Buffer, endA - ansi.Buffer );
*end = (LPWSTR)s + len/sizeof(WCHAR);
}
RtlFreeAnsiString( &ansi );
return ret;
} }
/********************************************************************* /*********************************************************************
* wcstoul (NTDLL.@) * wcstoul (NTDLL.@)
* Like strtoul, but for wide character strings.
*/ */
INT __cdecl NTDLL_wcstoul(LPCWSTR s,LPWSTR *end,INT base) unsigned long __cdecl NTDLL_wcstoul(LPCWSTR s,LPWSTR *end,INT base)
{ {
UNICODE_STRING uni; return strtoulW( s, end, base );
ANSI_STRING ansi;
INT ret;
LPSTR endA;
RtlInitUnicodeString( &uni, s );
RtlUnicodeStringToAnsiString( &ansi, &uni, TRUE );
ret = strtoul( ansi.Buffer, &endA, base );
if (end)
{
DWORD len;
RtlMultiByteToUnicodeSize( &len, ansi.Buffer, endA - ansi.Buffer );
*end = (LPWSTR)s + len/sizeof(WCHAR);
}
RtlFreeAnsiString( &ansi );
return ret;
} }
@ -405,19 +373,17 @@ LPWSTR __cdecl _ultow(ULONG value, LPWSTR string, INT radix)
* _wtol (NTDLL.@) * _wtol (NTDLL.@)
* Like atol, but for wide character strings. * Like atol, but for wide character strings.
*/ */
LONG __cdecl _wtol(LPWSTR string) LONG __cdecl NTDLL__wtol(LPWSTR string)
{ {
char buffer[30]; return strtolW( string, NULL, 10 );
NTDLL_wcstombs( buffer, string, sizeof(buffer) );
return atol( buffer );
} }
/********************************************************************* /*********************************************************************
* _wtoi (NTDLL.@) * _wtoi (NTDLL.@)
*/ */
INT __cdecl _wtoi(LPWSTR string) INT __cdecl NTDLL__wtoi(LPWSTR string)
{ {
return _wtol(string); return NTDLL__wtol(string);
} }
/* INTERNAL: Wide char snprintf /* INTERNAL: Wide char snprintf

View File

@ -6,7 +6,7 @@ MODULE = oleaut32.dll
IMPORTS = ole32 user32 gdi32 advapi32 kernel32 ntdll IMPORTS = ole32 user32 gdi32 advapi32 kernel32 ntdll
DELAYIMPORTS = comctl32 DELAYIMPORTS = comctl32
ALTNAMES = ole2disp.dll typelib.dll ALTNAMES = ole2disp.dll typelib.dll
EXTRALIBS = $(LIBUUID) @JPEGLIB@ EXTRALIBS = $(LIBUNICODE) $(LIBUUID) @JPEGLIB@
LDDLLFLAGS = @LDDLLFLAGS@ LDDLLFLAGS = @LDDLLFLAGS@
SYMBOLFILE = $(MODULE).tmp.o SYMBOLFILE = $(MODULE).tmp.o

View File

@ -70,7 +70,6 @@
#include "ole2disp.h" #include "ole2disp.h"
#include "typelib.h" #include "typelib.h"
#include "wine/debug.h" #include "wine/debug.h"
#include "ntddk.h"
WINE_DEFAULT_DEBUG_CHANNEL(ole); WINE_DEFAULT_DEBUG_CHANNEL(ole);
WINE_DECLARE_DEBUG_CHANNEL(typelib); WINE_DECLARE_DEBUG_CHANNEL(typelib);
@ -287,7 +286,7 @@ HRESULT WINAPI LoadTypeLibEx(
/* Look for a trailing '\\' followed by an index */ /* Look for a trailing '\\' followed by an index */
pIndexStr = strrchrW(szFile, '\\'); pIndexStr = strrchrW(szFile, '\\');
if(pIndexStr && pIndexStr != szFile && *++pIndexStr != '\0') { if(pIndexStr && pIndexStr != szFile && *++pIndexStr != '\0') {
index = wcstol(pIndexStr, NULL, 10); index = atoiW(pIndexStr);
memcpy(szFileCopy, szFile, memcpy(szFileCopy, szFile,
(pIndexStr - szFile - 1) * sizeof(WCHAR)); (pIndexStr - szFile - 1) * sizeof(WCHAR));
szFileCopy[pIndexStr - szFile - 1] = '\0'; szFileCopy[pIndexStr - szFile - 1] = '\0';

View File

@ -315,7 +315,7 @@ static BOOL do_reg_operation( HKEY hkey, const WCHAR *value, INFCONTEXT *context
if (type == REG_DWORD) if (type == REG_DWORD)
{ {
DWORD dw = str ? wcstol( str, NULL, 16 ) : 0; DWORD dw = str ? strtolW( str, NULL, 16 ) : 0;
TRACE( "setting dword %s to %lx\n", debugstr_w(value), dw ); TRACE( "setting dword %s to %lx\n", debugstr_w(value), dw );
RegSetValueExW( hkey, value, 0, type, (BYTE *)&dw, sizeof(dw) ); RegSetValueExW( hkey, value, 0, type, (BYTE *)&dw, sizeof(dw) );
} }

View File

@ -327,7 +327,7 @@ static const WCHAR *get_string_subst( struct inf_file *file, const WCHAR *str, u
{ {
memcpy( dirid_str, str, *len * sizeof(WCHAR) ); memcpy( dirid_str, str, *len * sizeof(WCHAR) );
dirid_str[*len] = 0; dirid_str[*len] = 0;
dirid = wcstol( dirid_str, &end, 10 ); dirid = strtolW( dirid_str, &end, 10 );
if (!*end) ret = get_dirid_subst( dirid, len ); if (!*end) ret = get_dirid_subst( dirid, len );
HeapFree( GetProcessHeap(), 0, dirid_str ); HeapFree( GetProcessHeap(), 0, dirid_str );
return ret; return ret;

View File

@ -759,7 +759,6 @@ DWORD WINAPI RtlIsTextUnicode(
DWORD len, DWORD len,
DWORD *pf); DWORD *pf);
INT __cdecl wcstol(LPCWSTR,LPWSTR*,INT);
int __cdecl swprintf(LPWSTR,LPCWSTR,...); int __cdecl swprintf(LPWSTR,LPCWSTR,...);
/* resource functions */ /* resource functions */

View File

@ -71,6 +71,12 @@ extern int cp_wcstombs( const union cptable *table, int flags,
extern int utf8_wcstombs( const WCHAR *src, int srclen, char *dst, int dstlen ); extern int utf8_wcstombs( const WCHAR *src, int srclen, char *dst, int dstlen );
extern int utf8_mbstowcs( int flags, const char *src, int srclen, WCHAR *dst, int dstlen ); extern int utf8_mbstowcs( int flags, const char *src, int srclen, WCHAR *dst, int dstlen );
extern int strcmpiW( const WCHAR *str1, const WCHAR *str2 );
extern int strncmpiW( const WCHAR *str1, const WCHAR *str2, int n );
extern WCHAR *strstrW( const WCHAR *str, const WCHAR *sub );
extern long int strtolW( const WCHAR *nptr, WCHAR **endptr, int base );
extern unsigned long int strtoulW( const WCHAR *nptr, WCHAR **endptr, int base );
static inline int is_dbcs_leadbyte( const union cptable *table, unsigned char ch ) static inline int is_dbcs_leadbyte( const union cptable *table, unsigned char ch )
{ {
return (table->info.char_size == 2) && (table->dbcs.cp2uni_leadbytes[ch]); return (table->info.char_size == 2) && (table->dbcs.cp2uni_leadbytes[ch]);
@ -244,8 +250,14 @@ static inline WCHAR *struprW( WCHAR *str )
return ret; return ret;
} }
extern int strcmpiW( const WCHAR *str1, const WCHAR *str2 ); static inline long int atolW( const WCHAR *str )
extern int strncmpiW( const WCHAR *str1, const WCHAR *str2, int n ); {
extern WCHAR *strstrW( const WCHAR *str, const WCHAR *sub ); return strtolW( str, (WCHAR **)0, 10 );
}
static inline int atoiW( const WCHAR *str )
{
return (int)atolW( str );
}
#endif /* __WINE_UNICODE_H */ #endif /* __WINE_UNICODE_H */

View File

@ -18,6 +18,8 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/ */
#include <limits.h>
#include "wine/unicode.h" #include "wine/unicode.h"
int strcmpiW( const WCHAR *str1, const WCHAR *str2 ) int strcmpiW( const WCHAR *str1, const WCHAR *str2 )
@ -50,3 +52,237 @@ WCHAR *strstrW( const WCHAR *str, const WCHAR *sub )
} }
return NULL; return NULL;
} }
/* strtolW and strtoulW implementation based on the GNU C library code */
/* Copyright (C) 1991,92,94,95,96,97,98,99,2000,2001 Free Software Foundation, Inc. */
long int strtolW( const WCHAR *nptr, WCHAR **endptr, int base )
{
int negative;
register unsigned long int cutoff;
register unsigned int cutlim;
register unsigned long int i;
register const WCHAR *s;
register WCHAR c;
const WCHAR *save, *end;
int overflow;
if (base < 0 || base == 1 || base > 36) return 0;
save = s = nptr;
/* Skip white space. */
while (isspaceW (*s))
++s;
if (!*s) goto noconv;
/* Check for a sign. */
negative = 0;
if (*s == '-')
{
negative = 1;
++s;
}
else if (*s == '+')
++s;
/* Recognize number prefix and if BASE is zero, figure it out ourselves. */
if (*s == '0')
{
if ((base == 0 || base == 16) && toupperW(s[1]) == 'X')
{
s += 2;
base = 16;
}
else if (base == 0)
base = 8;
}
else if (base == 0)
base = 10;
/* Save the pointer so we can check later if anything happened. */
save = s;
end = NULL;
cutoff = ULONG_MAX / (unsigned long int) base;
cutlim = ULONG_MAX % (unsigned long int) base;
overflow = 0;
i = 0;
c = *s;
for (;c != '\0'; c = *++s)
{
if (s == end)
break;
if (c >= '0' && c <= '9')
c -= '0';
else if (isalphaW (c))
c = toupperW (c) - 'A' + 10;
else
break;
if ((int) c >= base)
break;
/* Check for overflow. */
if (i > cutoff || (i == cutoff && c > cutlim))
overflow = 1;
else
{
i *= (unsigned long int) base;
i += c;
}
}
/* Check if anything actually happened. */
if (s == save)
goto noconv;
/* Store in ENDPTR the address of one character
past the last character we converted. */
if (endptr != NULL)
*endptr = (WCHAR *)s;
/* Check for a value that is within the range of
`unsigned LONG int', but outside the range of `LONG int'. */
if (overflow == 0
&& i > (negative
? -((unsigned long int) (LONG_MIN + 1)) + 1
: (unsigned long int) LONG_MAX))
overflow = 1;
if (overflow)
{
return negative ? LONG_MIN : LONG_MAX;
}
/* Return the result of the appropriate sign. */
return negative ? -i : i;
noconv:
/* We must handle a special case here: the base is 0 or 16 and the
first two characters are '0' and 'x', but the rest are no
hexadecimal digits. This is no error case. We return 0 and
ENDPTR points to the `x`. */
if (endptr != NULL)
{
if (save - nptr >= 2 && toupperW (save[-1]) == 'X'
&& save[-2] == '0')
*endptr = (WCHAR *)&save[-1];
else
/* There was no number to convert. */
*endptr = (WCHAR *)nptr;
}
return 0L;
}
unsigned long int strtoulW( const WCHAR *nptr, WCHAR **endptr, int base )
{
int negative;
register unsigned long int cutoff;
register unsigned int cutlim;
register unsigned long int i;
register const WCHAR *s;
register WCHAR c;
const WCHAR *save, *end;
int overflow;
if (base < 0 || base == 1 || base > 36) return 0;
save = s = nptr;
/* Skip white space. */
while (isspaceW (*s))
++s;
if (!*s) goto noconv;
/* Check for a sign. */
negative = 0;
if (*s == '-')
{
negative = 1;
++s;
}
else if (*s == '+')
++s;
/* Recognize number prefix and if BASE is zero, figure it out ourselves. */
if (*s == '0')
{
if ((base == 0 || base == 16) && toupperW(s[1]) == 'X')
{
s += 2;
base = 16;
}
else if (base == 0)
base = 8;
}
else if (base == 0)
base = 10;
/* Save the pointer so we can check later if anything happened. */
save = s;
end = NULL;
cutoff = ULONG_MAX / (unsigned long int) base;
cutlim = ULONG_MAX % (unsigned long int) base;
overflow = 0;
i = 0;
c = *s;
for (;c != '\0'; c = *++s)
{
if (s == end)
break;
if (c >= '0' && c <= '9')
c -= '0';
else if (isalphaW (c))
c = toupperW (c) - 'A' + 10;
else
break;
if ((int) c >= base)
break;
/* Check for overflow. */
if (i > cutoff || (i == cutoff && c > cutlim))
overflow = 1;
else
{
i *= (unsigned long int) base;
i += c;
}
}
/* Check if anything actually happened. */
if (s == save)
goto noconv;
/* Store in ENDPTR the address of one character
past the last character we converted. */
if (endptr != NULL)
*endptr = (WCHAR *)s;
if (overflow)
{
return ULONG_MAX;
}
/* Return the result of the appropriate sign. */
return negative ? -i : i;
noconv:
/* We must handle a special case here: the base is 0 or 16 and the
first two characters are '0' and 'x', but the rest are no
hexadecimal digits. This is no error case. We return 0 and
ENDPTR points to the `x`. */
if (endptr != NULL)
{
if (save - nptr >= 2 && toupperW (save[-1]) == 'X'
&& save[-2] == '0')
*endptr = (WCHAR *)&save[-1];
else
/* There was no number to convert. */
*endptr = (WCHAR *)nptr;
}
return 0L;
}