Andrew Nguyen : msvcrt: Implement _ultoa_s.
Alexandre Julliard
julliard at winehq.org
Thu Oct 21 10:50:46 CDT 2010
Module: wine
Branch: master
Commit: ed357e5ca6ebbb52a07c75c0a0f1eade3b89d923
URL: http://source.winehq.org/git/wine.git/?a=commit;h=ed357e5ca6ebbb52a07c75c0a0f1eade3b89d923
Author: Andrew Nguyen <anguyen at codeweavers.com>
Date: Thu Oct 21 02:57:44 2010 -0500
msvcrt: Implement _ultoa_s.
---
dlls/msvcr100/msvcr100.spec | 2 +-
dlls/msvcr80/msvcr80.spec | 2 +-
dlls/msvcr90/msvcr90.spec | 2 +-
dlls/msvcrt/msvcrt.spec | 2 +-
dlls/msvcrt/string.c | 54 ++++++++++++++++++++++++++++
dlls/msvcrt/tests/string.c | 81 +++++++++++++++++++++++++++++++++++++++++++
include/msvcrt/stdlib.h | 1 +
7 files changed, 140 insertions(+), 4 deletions(-)
diff --git a/dlls/msvcr100/msvcr100.spec b/dlls/msvcr100/msvcr100.spec
index 212f30e..ec0a1ba 100644
--- a/dlls/msvcr100/msvcr100.spec
+++ b/dlls/msvcr100/msvcr100.spec
@@ -1199,7 +1199,7 @@
@ cdecl _ui64tow(int64 ptr long) msvcrt._ui64tow
@ stub _ui64tow_s
@ cdecl _ultoa(long ptr long) msvcrt._ultoa
-@ stub _ultoa_s
+@ cdecl _ultoa_s(long ptr long long) msvcrt._ultoa_s
@ cdecl _ultow(long ptr long) msvcrt._ultow
@ stub _ultow_s
@ cdecl _umask(long) msvcrt._umask
diff --git a/dlls/msvcr80/msvcr80.spec b/dlls/msvcr80/msvcr80.spec
index 43c0032..a5bb126 100644
--- a/dlls/msvcr80/msvcr80.spec
+++ b/dlls/msvcr80/msvcr80.spec
@@ -1052,7 +1052,7 @@
@ cdecl _ui64tow(int64 ptr long) msvcrt._ui64tow
@ stub _ui64tow_s
@ cdecl _ultoa(long ptr long) msvcrt._ultoa
-@ stub _ultoa_s
+@ cdecl _ultoa_s(long ptr long long) msvcrt._ultoa_s
@ cdecl _ultow(long ptr long) msvcrt._ultow
@ stub _ultow_s
@ cdecl _umask(long) msvcrt._umask
diff --git a/dlls/msvcr90/msvcr90.spec b/dlls/msvcr90/msvcr90.spec
index 74480af..14eec1b 100644
--- a/dlls/msvcr90/msvcr90.spec
+++ b/dlls/msvcr90/msvcr90.spec
@@ -1039,7 +1039,7 @@
@ cdecl _ui64tow(int64 ptr long) msvcrt._ui64tow
@ stub _ui64tow_s
@ cdecl _ultoa(long ptr long) msvcrt._ultoa
-@ stub _ultoa_s
+@ cdecl _ultoa_s(long ptr long long) msvcrt._ultoa_s
@ cdecl _ultow(long ptr long) msvcrt._ultow
@ stub _ultow_s
@ cdecl _umask(long) msvcrt._umask
diff --git a/dlls/msvcrt/msvcrt.spec b/dlls/msvcrt/msvcrt.spec
index 1b3739f..1e8f06d 100644
--- a/dlls/msvcrt/msvcrt.spec
+++ b/dlls/msvcrt/msvcrt.spec
@@ -974,7 +974,7 @@
@ cdecl _ui64tow(int64 ptr long) ntdll._ui64tow
# stub _ui64tow_s
@ cdecl _ultoa(long ptr long) ntdll._ultoa
-# stub _ultoa_s
+@ cdecl _ultoa_s(long ptr long long)
@ cdecl _ultow(long ptr long) ntdll._ultow
# stub _ultow_s
@ cdecl _umask(long) MSVCRT__umask
diff --git a/dlls/msvcrt/string.c b/dlls/msvcrt/string.c
index 02bd0a5..944c7e6 100644
--- a/dlls/msvcrt/string.c
+++ b/dlls/msvcrt/string.c
@@ -784,6 +784,60 @@ int CDECL MSVCRT__ui64toa_s(unsigned __int64 value, char *str,
return 0;
}
+/*********************************************************************
+ * _ultoa_s (MSVCRT.@)
+ */
+int CDECL _ultoa_s(MSVCRT_ulong value, char *str, MSVCRT_size_t size, int radix)
+{
+ MSVCRT_ulong digit;
+ char buffer[33], *pos;
+ size_t len;
+
+ if (!str || !size || radix < 2 || radix > 36)
+ {
+ if (str && size)
+ str[0] = '\0';
+
+ *MSVCRT__errno() = MSVCRT_EINVAL;
+ return MSVCRT_EINVAL;
+ }
+
+ pos = buffer + 32;
+ *pos = '\0';
+
+ do
+ {
+ digit = value % radix;
+ value /= radix;
+
+ if (digit < 10)
+ *--pos = '0' + digit;
+ else
+ *--pos = 'a' + digit - 10;
+ }
+ while (value != 0);
+
+ len = buffer + 33 - pos;
+ if (len > size)
+ {
+ size_t i;
+ char *p = str;
+
+ /* Copy the temporary buffer backwards up to the available number of
+ * characters. */
+
+ for (pos = buffer + 31, i = 0; i < size; i++)
+ *p++ = *pos--;
+
+ str[0] = '\0';
+ *MSVCRT__errno() = MSVCRT_ERANGE;
+ return MSVCRT_ERANGE;
+ }
+
+ memcpy(str, pos, len);
+ return 0;
+}
+
#define I10_OUTPUT_MAX_PREC 21
/* Internal structure used by $I10_OUTPUT */
struct _I10_OUTPUT_DATA {
diff --git a/dlls/msvcrt/tests/string.c b/dlls/msvcrt/tests/string.c
index 9f7370e..ab647db 100644
--- a/dlls/msvcrt/tests/string.c
+++ b/dlls/msvcrt/tests/string.c
@@ -63,6 +63,7 @@ static int (__cdecl *pmbstowcs_s)(size_t*,wchar_t*,size_t,const char*,size_t);
static errno_t (__cdecl *p_gcvt_s)(char*,size_t,double,int);
static errno_t (__cdecl *p_itoa_s)(int,char*,size_t,int);
static errno_t (__cdecl *p_strlwr_s)(char*,size_t);
+static errno_t (__cdecl *p_ultoa_s)(__msvcrt_ulong,char*,size_t,int);
static int *p__mb_cur_max;
static unsigned char *p_mbctype;
@@ -1596,6 +1597,84 @@ static void test__mbsnbcat_s(void)
"Expected the output buffer string to be \"\\0inosaurdu\" without ending null terminator\n");
}
+static void test__ultoa_s(void)
+{
+ errno_t ret;
+ char buffer[33];
+
+ if (!p_ultoa_s)
+ {
+ win_skip("Skipping _ultoa_s tests\n");
+ return;
+ }
+
+ errno = EBADF;
+ ret = p_ultoa_s(0, NULL, 0, 0);
+ ok(ret == EINVAL, "Expected _ultoa_s to return EINVAL, got %d\n", ret);
+ ok(errno == EINVAL, "Expected errno to be EINVAL, got %d\n", errno);
+
+ memset(buffer, 'X', sizeof(buffer));
+ errno = EBADF;
+ ret = p_ultoa_s(0, buffer, 0, 0);
+ ok(ret == EINVAL, "Expected _ultoa_s to return EINVAL, got %d\n", ret);
+ ok(errno == EINVAL, "Expected errno to be EINVAL, got %d\n", errno);
+ ok(buffer[0] == 'X', "Expected the output buffer to be untouched\n");
+
+ memset(buffer, 'X', sizeof(buffer));
+ errno = EBADF;
+ ret = p_ultoa_s(0, buffer, sizeof(buffer), 0);
+ ok(ret == EINVAL, "Expected _ultoa_s to return EINVAL, got %d\n", ret);
+ ok(errno == EINVAL, "Expected errno to be EINVAL, got %d\n", errno);
+ ok(buffer[0] == '\0', "Expected the output buffer to be null terminated\n");
+
+ memset(buffer, 'X', sizeof(buffer));
+ errno = EBADF;
+ ret = p_ultoa_s(0, buffer, sizeof(buffer), 64);
+ ok(ret == EINVAL, "Expected _ultoa_s to return EINVAL, got %d\n", ret);
+ ok(errno == EINVAL, "Expected errno to be EINVAL, got %d\n", errno);
+ ok(buffer[0] == '\0', "Expected the output buffer to be null terminated\n");
+
+ memset(buffer, 'X', sizeof(buffer));
+ errno = EBADF;
+ ret = p_ultoa_s(12345678, buffer, 4, 10);
+ ok(ret == ERANGE, "Expected _ultoa_s to return ERANGE, got %d\n", ret);
+ ok(errno == ERANGE, "Expected errno to be ERANGE, got %d\n", errno);
+ ok(!memcmp(buffer, "\000765", 4),
+ "Expected the output buffer to be null terminated with truncated output\n");
+
+ memset(buffer, 'X', sizeof(buffer));
+ errno = EBADF;
+ ret = p_ultoa_s(12345678, buffer, 8, 10);
+ ok(ret == ERANGE, "Expected _ultoa_s to return ERANGE, got %d\n", ret);
+ ok(errno == ERANGE, "Expected errno to be ERANGE, got %d\n", errno);
+ ok(!memcmp(buffer, "\0007654321", 8),
+ "Expected the output buffer to be null terminated with truncated output\n");
+
+ ret = p_ultoa_s(12345678, buffer, 9, 10);
+ ok(ret == 0, "Expected _ultoa_s to return 0, got %d\n", ret);
+ ok(!strcmp(buffer, "12345678"),
+ "Expected output buffer string to be \"12345678\", got \"%s\"\n",
+ buffer);
+
+ ret = p_ultoa_s(43690, buffer, sizeof(buffer), 2);
+ ok(ret == 0, "Expected _ultoa_s to return 0, got %d\n", ret);
+ ok(!strcmp(buffer, "1010101010101010"),
+ "Expected output buffer string to be \"1010101010101010\", got \"%s\"\n",
+ buffer);
+
+ ret = p_ultoa_s(1092009, buffer, sizeof(buffer), 36);
+ ok(ret == 0, "Expected _ultoa_s to return 0, got %d\n", ret);
+ ok(!strcmp(buffer, "nell"),
+ "Expected output buffer string to be \"nell\", got \"%s\"\n",
+ buffer);
+
+ ret = p_ultoa_s(5704, buffer, sizeof(buffer), 18);
+ ok(ret == 0, "Expected _ultoa_s to return 0, got %d\n", ret);
+ ok(!strcmp(buffer, "hag"),
+ "Expected output buffer string to be \"hag\", got \"%s\"\n",
+ buffer);
+}
+
START_TEST(string)
{
char mem[100];
@@ -1625,6 +1704,7 @@ START_TEST(string)
p_gcvt_s = (void *)GetProcAddress(hMsvcrt, "_gcvt_s");
p_itoa_s = (void *)GetProcAddress(hMsvcrt, "_itoa_s");
p_strlwr_s = (void *)GetProcAddress(hMsvcrt, "_strlwr_s");
+ p_ultoa_s = (void *)GetProcAddress(hMsvcrt, "_ultoa_s");
/* MSVCRT memcpy behaves like memmove for overlapping moves,
MFC42 CString::Insert seems to rely on that behaviour */
@@ -1663,4 +1743,5 @@ START_TEST(string)
test__strlwr_s();
test_wcsncat_s();
test__mbsnbcat_s();
+ test__ultoa_s();
}
diff --git a/include/msvcrt/stdlib.h b/include/msvcrt/stdlib.h
index 086c3e1..49783c0 100644
--- a/include/msvcrt/stdlib.h
+++ b/include/msvcrt/stdlib.h
@@ -169,6 +169,7 @@ void __cdecl _swab(char*,char*,int);
char* __cdecl _ui64toa(unsigned __int64,char*,int);
errno_t __cdecl _ui64toa_s(unsigned __int64,char*,size_t,int);
char* __cdecl _ultoa(__msvcrt_ulong,char*,int);
+errno_t __cdecl _ultoa_s(__msvcrt_ulong,char*,size_t,int);
void __cdecl _exit(int);
void __cdecl abort(void);
More information about the wine-cvs
mailing list