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);
INT __cdecl _wtoi(LPWSTR string);
/**************************************************************************
* DPA_LoadStream [COMCTL32.9]
*
@ -2483,7 +2481,7 @@ COMCTL32_StrToIntA (LPSTR lpString)
INT WINAPI
COMCTL32_StrToIntW (LPWSTR lpString)
{
return _wtoi(lpString);
return atoiW(lpString);
}

View File

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

View File

@ -30,6 +30,7 @@
#include "commctrl.h"
#include "winnls.h"
#include "ntddk.h"
#include "wine/unicode.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(updown);
@ -275,7 +276,7 @@ static BOOL UPDOWN_GetBuddyInt (UPDOWN_INFO *infoPtr)
*dst = 0;
/* 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;
}

View File

@ -884,7 +884,7 @@ name ntdll
@ cdecl _itoa(long ptr long) _itoa
@ cdecl _ltoa(long ptr long) _ltoa
@ 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 _snwprintf(wstr long wstr) _snwprintf
@ cdecl _splitpath(str ptr ptr ptr ptr) _splitpath
@ -900,8 +900,8 @@ name ntdll
@ cdecl _wcslwr(wstr) NTDLL__wcslwr
@ cdecl _wcsnicmp(wstr wstr long) NTDLL__wcsnicmp
@ cdecl _wcsupr(wstr) NTDLL__wcsupr
@ cdecl _wtoi(wstr) _wtoi
@ cdecl _wtol(wstr) _wtol
@ cdecl _wtoi(wstr) NTDLL__wtoi
@ cdecl _wtol(wstr) NTDLL__wtol
@ cdecl -noimport abs(long) abs
@ cdecl -noimport atan(double) atan
@ cdecl -noimport atoi(str) atoi

View File

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

View File

@ -303,51 +303,19 @@ INT __cdecl NTDLL_mbstowcs( LPWSTR dst, LPCSTR src, INT n )
/*********************************************************************
* 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;
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;
return strtolW( s, end, base );
}
/*********************************************************************
* 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;
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;
return strtoulW( s, end, base );
}
@ -405,19 +373,17 @@ LPWSTR __cdecl _ultow(ULONG value, LPWSTR string, INT radix)
* _wtol (NTDLL.@)
* Like atol, but for wide character strings.
*/
LONG __cdecl _wtol(LPWSTR string)
LONG __cdecl NTDLL__wtol(LPWSTR string)
{
char buffer[30];
NTDLL_wcstombs( buffer, string, sizeof(buffer) );
return atol( buffer );
return strtolW( string, NULL, 10 );
}
/*********************************************************************
* _wtoi (NTDLL.@)
*/
INT __cdecl _wtoi(LPWSTR string)
INT __cdecl NTDLL__wtoi(LPWSTR string)
{
return _wtol(string);
return NTDLL__wtol(string);
}
/* INTERNAL: Wide char snprintf

View File

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

View File

@ -70,7 +70,6 @@
#include "ole2disp.h"
#include "typelib.h"
#include "wine/debug.h"
#include "ntddk.h"
WINE_DEFAULT_DEBUG_CHANNEL(ole);
WINE_DECLARE_DEBUG_CHANNEL(typelib);
@ -287,7 +286,7 @@ HRESULT WINAPI LoadTypeLibEx(
/* Look for a trailing '\\' followed by an index */
pIndexStr = strrchrW(szFile, '\\');
if(pIndexStr && pIndexStr != szFile && *++pIndexStr != '\0') {
index = wcstol(pIndexStr, NULL, 10);
index = atoiW(pIndexStr);
memcpy(szFileCopy, szFile,
(pIndexStr - szFile - 1) * sizeof(WCHAR));
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)
{
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 );
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) );
dirid_str[*len] = 0;
dirid = wcstol( dirid_str, &end, 10 );
dirid = strtolW( dirid_str, &end, 10 );
if (!*end) ret = get_dirid_subst( dirid, len );
HeapFree( GetProcessHeap(), 0, dirid_str );
return ret;

View File

@ -759,7 +759,6 @@ DWORD WINAPI RtlIsTextUnicode(
DWORD len,
DWORD *pf);
INT __cdecl wcstol(LPCWSTR,LPWSTR*,INT);
int __cdecl swprintf(LPWSTR,LPCWSTR,...);
/* 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_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 )
{
return (table->info.char_size == 2) && (table->dbcs.cp2uni_leadbytes[ch]);
@ -244,8 +250,14 @@ static inline WCHAR *struprW( WCHAR *str )
return ret;
}
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 );
static inline long int atolW( const WCHAR *str )
{
return strtolW( str, (WCHAR **)0, 10 );
}
static inline int atoiW( const WCHAR *str )
{
return (int)atolW( str );
}
#endif /* __WINE_UNICODE_H */

View File

@ -18,6 +18,8 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <limits.h>
#include "wine/unicode.h"
int strcmpiW( const WCHAR *str1, const WCHAR *str2 )
@ -50,3 +52,237 @@ WCHAR *strstrW( const WCHAR *str, const WCHAR *sub )
}
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;
}