[PATCH v3 2/3] libwine: Add strtoullW.
Daniel Lehman
dlehman25 at gmail.com
Tue Sep 3 20:41:33 CDT 2019
Signed-off-by: Daniel Lehman <dlehman25 at gmail.com>
---
include/wine/unicode.h | 1 +
libs/port/string.c | 113 +++++++++++++++++++++++++++++++++++++++++
libs/wine/wine.map | 1 +
3 files changed, 115 insertions(+)
diff --git a/include/wine/unicode.h b/include/wine/unicode.h
index ff6f6568a5..5ee53e74a5 100644
--- a/include/wine/unicode.h
+++ b/include/wine/unicode.h
@@ -108,6 +108,7 @@ extern int memicmpW( 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 );
+extern unsigned long long strtoullW( const WCHAR *nptr, WCHAR **endptr, int base );
extern int sprintfW( WCHAR *str, const WCHAR *format, ... );
extern int snprintfW( WCHAR *str, size_t len, const WCHAR *format, ... );
extern int vsprintfW( WCHAR *str, const WCHAR *format, va_list valist );
diff --git a/libs/port/string.c b/libs/port/string.c
index c3388bcc7d..0ff4700664 100644
--- a/libs/port/string.c
+++ b/libs/port/string.c
@@ -301,6 +301,119 @@ noconv:
}
+unsigned long long strtoullW( const WCHAR *nptr, WCHAR **endptr, int base )
+{
+ int negative;
+ register unsigned long long cutoff;
+ register unsigned int cutlim;
+ register unsigned long long 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 = ULLONG_MAX / (unsigned long long) base;
+ cutlim = ULLONG_MAX % (unsigned long long) 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 long) 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)
+ {
+ errno = ERANGE;
+ return ULLONG_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 not
+ 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 0;
+}
+
+
/* format a WCHAR string according to a printf format; helper for vsnprintfW */
static size_t format_string( WCHAR *buffer, size_t len, const char *format, const WCHAR *str, int str_len )
{
diff --git a/libs/wine/wine.map b/libs/wine/wine.map
index 2159fac852..741ae759de 100644
--- a/libs/wine/wine.map
+++ b/libs/wine/wine.map
@@ -44,6 +44,7 @@ WINE_1.0
strstrW;
strtolW;
strtoulW;
+ strtoullW;
struprW;
tolowerW;
toupperW;
--
2.17.1
More information about the wine-devel
mailing list