[4/6] msvcirt: Implement istream::operator>> for integers.

Iván Matellanes matellanesivan at gmail.com
Mon Aug 1 05:40:41 CDT 2016


Signed-off-by: Iván Matellanes <matellanes.ivan at gmail.com>
---
 dlls/msvcirt/msvcirt.c       |  90 ++++++++++++++++++++++++++----
 dlls/msvcirt/tests/msvcirt.c | 128 ++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 205 insertions(+), 13 deletions(-)

diff --git a/dlls/msvcirt/msvcirt.c b/dlls/msvcirt/msvcirt.c
index 66bee72..608aeed 100644
--- a/dlls/msvcirt/msvcirt.c
+++ b/dlls/msvcirt/msvcirt.c
@@ -19,8 +19,10 @@
 
 #include "config.h"
 
+#include <errno.h>
 #include <fcntl.h>
 #include <io.h>
+#include <limits.h>
 #include <share.h>
 #include <stdarg.h>
 #include <stdio.h>
@@ -3539,13 +3541,82 @@ istream* __thiscall istream_read_str(istream *this, char *str)
     return this;
 }
 
+static istream* istream_internal_read_integer(istream *this, void *p, int size)
+{
+    /* size: 0 => short, 1 => int, 2 => long */
+    ios *base = istream_get_ios(this);
+    char buffer[16];
+    int num_base;
+    LONG min_value[3] = {SHRT_MIN, INT_MIN, LONG_MIN}, tmp;
+    LONG max_value[3] = {SHRT_MAX, INT_MAX, LONG_MAX};
+
+    TRACE("(%p %p %d)\n", this, p, size);
+
+    if (istream_ipfx(this, 0)) {
+        num_base = istream_getint(this, buffer);
+        errno = 0;
+        tmp = strtol(buffer, NULL, num_base);
+        /* check for overflow and whether the value fits in the output var */
+        if (size == 2 && errno == ERANGE) {
+            base->state |= IOSTATE_failbit;
+        } else if (tmp > max_value[size]) {
+            base->state |= IOSTATE_failbit;
+            tmp = max_value[size];
+        } else if (tmp < min_value[size]) {
+            base->state |= IOSTATE_failbit;
+            tmp = min_value[size];
+        }
+        /* assign the value to the output parameter */
+        if (size == 0)
+            *((short*) p) = tmp;
+        else if (size == 1)
+            *((int*) p) = tmp;
+        else
+            *((LONG*) p) = tmp;
+        istream_isfx(this);
+    }
+    return this;
+}
+
+static istream* istream_internal_read_unsigned_integer(istream *this, void *p, int size)
+{
+    /* size: 0 => short, 1 => int, 2 => long */
+    ios *base = istream_get_ios(this);
+    char buffer[16];
+    int num_base;
+    LONG min_value[3] = {SHRT_MIN, INT_MIN, LONG_MIN};
+    ULONG umax_value[3] = {USHRT_MAX, UINT_MAX, ULONG_MAX}, tmp;
+
+    TRACE("(%p %p %d)\n", this, p, size);
+
+    if (istream_ipfx(this, 0)) {
+        num_base = istream_getint(this, buffer);
+        errno = 0;
+        tmp = strtoul(buffer, NULL, num_base);
+        /* check for overflow and whether the value fits in the output var */
+        if ((tmp == ULONG_MAX && errno == ERANGE) ||
+            (tmp > umax_value[size] && tmp < (ULONG) min_value[size])) {
+            base->state |= IOSTATE_failbit;
+            tmp = umax_value[size];
+        }
+        /* assign the value to the output parameter */
+        if (size == 0)
+            *((unsigned short*) p) = tmp;
+        else if (size == 1)
+            *((unsigned int*) p) = tmp;
+        else
+            *((ULONG*) p) = tmp;
+        istream_isfx(this);
+    }
+    return this;
+}
+
 /* ??5istream@@QAEAAV0 at AAF@Z */
 /* ??5istream@@QEAAAEAV0 at AEAF@Z */
 DEFINE_THISCALL_WRAPPER(istream_read_short, 8)
 istream* __thiscall istream_read_short(istream *this, short *p)
 {
-    FIXME("(%p %p) stub\n", this, p);
-    return this;
+    return istream_internal_read_integer(this, p, 0);
 }
 
 /* ??5istream@@QAEAAV0 at AAG@Z */
@@ -3553,8 +3624,7 @@ istream* __thiscall istream_read_short(istream *this, short *p)
 DEFINE_THISCALL_WRAPPER(istream_read_unsigned_short, 8)
 istream* __thiscall istream_read_unsigned_short(istream *this, unsigned short *p)
 {
-    FIXME("(%p %p) stub\n", this, p);
-    return this;
+    return istream_internal_read_unsigned_integer(this, p, 0);
 }
 
 /* ??5istream@@QAEAAV0 at AAH@Z */
@@ -3562,8 +3632,7 @@ istream* __thiscall istream_read_unsigned_short(istream *this, unsigned short *p
 DEFINE_THISCALL_WRAPPER(istream_read_int, 8)
 istream* __thiscall istream_read_int(istream *this, int *p)
 {
-    FIXME("(%p %p) stub\n", this, p);
-    return this;
+    return istream_internal_read_integer(this, p, 1);
 }
 
 /* ??5istream@@QAEAAV0 at AAI@Z */
@@ -3571,8 +3640,7 @@ istream* __thiscall istream_read_int(istream *this, int *p)
 DEFINE_THISCALL_WRAPPER(istream_read_unsigned_int, 8)
 istream* __thiscall istream_read_unsigned_int(istream *this, unsigned int *p)
 {
-    FIXME("(%p %p) stub\n", this, p);
-    return this;
+    return istream_internal_read_unsigned_integer(this, p, 1);
 }
 
 /* ??5istream@@QAEAAV0 at AAJ@Z */
@@ -3580,8 +3648,7 @@ istream* __thiscall istream_read_unsigned_int(istream *this, unsigned int *p)
 DEFINE_THISCALL_WRAPPER(istream_read_long, 8)
 istream* __thiscall istream_read_long(istream *this, LONG *p)
 {
-    FIXME("(%p %p) stub\n", this, p);
-    return this;
+    return istream_internal_read_integer(this, p, 2);
 }
 
 /* ??5istream@@QAEAAV0 at AAK@Z */
@@ -3589,8 +3656,7 @@ istream* __thiscall istream_read_long(istream *this, LONG *p)
 DEFINE_THISCALL_WRAPPER(istream_read_unsigned_long, 8)
 istream* __thiscall istream_read_unsigned_long(istream *this, ULONG *p)
 {
-    FIXME("(%p %p) stub\n", this, p);
-    return this;
+    return istream_internal_read_unsigned_integer(this, p, 2);
 }
 
 /* ??5istream@@QAEAAV0 at AAM@Z */
diff --git a/dlls/msvcirt/tests/msvcirt.c b/dlls/msvcirt/tests/msvcirt.c
index 6d97566..fdb975a 100644
--- a/dlls/msvcirt/tests/msvcirt.c
+++ b/dlls/msvcirt/tests/msvcirt.c
@@ -329,6 +329,12 @@ static int (*__thiscall p_istream_getint)(istream*, char*);
 static int (*__thiscall p_istream_getdouble)(istream*, char*, int);
 static istream* (*__thiscall p_istream_read_char)(istream*, char*);
 static istream* (*__thiscall p_istream_read_str)(istream*, char*);
+static istream* (*__thiscall p_istream_read_short)(istream*, short*);
+static istream* (*__thiscall p_istream_read_unsigned_short)(istream*, unsigned short*);
+static istream* (*__thiscall p_istream_read_int)(istream*, int*);
+static istream* (*__thiscall p_istream_read_unsigned_int)(istream*, unsigned int*);
+static istream* (*__thiscall p_istream_read_long)(istream*, LONG*);
+static istream* (*__thiscall p_istream_read_unsigned_long)(istream*, ULONG*);
 
 /* Emulate a __thiscall */
 #ifdef __i386__
@@ -546,6 +552,12 @@ static BOOL init(void)
         SET(p_istream_getdouble, "?getdouble at istream@@AEAAHPEADH at Z");
         SET(p_istream_read_char, "??5istream@@QEAAAEAV0 at AEAD@Z");
         SET(p_istream_read_str, "??5istream@@QEAAAEAV0 at PEAD@Z");
+        SET(p_istream_read_short, "??5istream@@QEAAAEAV0 at AEAF@Z");
+        SET(p_istream_read_unsigned_short, "??5istream@@QEAAAEAV0 at AEAG@Z");
+        SET(p_istream_read_int, "??5istream@@QEAAAEAV0 at AEAH@Z");
+        SET(p_istream_read_unsigned_int, "??5istream@@QEAAAEAV0 at AEAI@Z");
+        SET(p_istream_read_long, "??5istream@@QEAAAEAV0 at AEAJ@Z");
+        SET(p_istream_read_unsigned_long, "??5istream@@QEAAAEAV0 at AEAK@Z");
     } else {
         p_operator_new = (void*)GetProcAddress(msvcrt, "??2 at YAPAXI@Z");
         p_operator_delete = (void*)GetProcAddress(msvcrt, "??3 at YAXPAX@Z");
@@ -685,6 +697,12 @@ static BOOL init(void)
         SET(p_istream_getdouble, "?getdouble at istream@@AAEHPADH at Z");
         SET(p_istream_read_char, "??5istream@@QAEAAV0 at AAD@Z");
         SET(p_istream_read_str, "??5istream@@QAEAAV0 at PAD@Z");
+        SET(p_istream_read_short, "??5istream@@QAEAAV0 at AAF@Z");
+        SET(p_istream_read_unsigned_short, "??5istream@@QAEAAV0 at AAG@Z");
+        SET(p_istream_read_int, "??5istream@@QAEAAV0 at AAH@Z");
+        SET(p_istream_read_unsigned_int, "??5istream@@QAEAAV0 at AAI@Z");
+        SET(p_istream_read_long, "??5istream@@QAEAAV0 at AAJ@Z");
+        SET(p_istream_read_unsigned_long, "??5istream@@QAEAAV0 at AAK@Z");
     }
     SET(p_ios_static_lock, "?x_lockc at ios@@0U_CRT_CRITICAL_SECTION@@A");
     SET(p_ios_lockc, "?lockc at ios@@KAXXZ");
@@ -4868,8 +4886,15 @@ static void test_istream_read(void)
 
     char c, st[8], char_out[] = {-85, ' ', 'a', -50};
     const char *str_out[] = {"AAAAAAA", "abc", "a", "abc", "ab", "abcde"};
+    short s, short_out[] = {32767, -32768};
+    unsigned short us, ushort_out[] = {65535u, 65534u, 32768u};
+    int n, int_out[] = {123456789, 0, 1, -500, 0x8000, 2147483646, 2147483647, -2147483647, -2147483648, -1};
+    unsigned un, uint_out[] = {4294967295u, 4294967294u, 2147483648u, 1u};
+    LONG l, long_out[] = {2147483647l, -2147483648l};
+    ULONG ul, ulong_out[] = {4294967295ul, 4294967294ul, 2147483648ul, 1ul};
     struct istream_read_test {
-        enum { type_chr, type_str } type;
+        enum { type_chr, type_str, type_shrt, type_ushrt, type_int, type_uint,
+            type_long, type_ulong } type;
         const char *stream_content;
         ios_flags flags;
         int width;
@@ -4902,6 +4927,71 @@ static void test_istream_read(void)
         {type_str, "abcde\n", 0,            0, /* "abcde" */   5, IOSTATE_goodbit, 0, 5, FALSE},
         {type_str, "\n",      0,            0, /* "AAAAAAA" */ 0, IOSTATE_failbit, 0, 0, FALSE},
         {type_str, "abcde",   0,           -1, /* "abcde" */   5, IOSTATE_eofbit,  0, 5, FALSE},
+        /* short */
+        {type_shrt, "32767",       0, 6, /* 32767 */  0, IOSTATE_eofbit,  6, 5,  FALSE},
+        {type_shrt, "32768",       0, 6, /* 32767 */  0, IOSTATE_faileof, 6, 5,  FALSE},
+        {type_shrt, "2147483648",  0, 6, /* 32767 */  0, IOSTATE_faileof, 6, 10, FALSE},
+        {type_shrt, "4294967296",  0, 6, /* 32767 */  0, IOSTATE_faileof, 6, 10, FALSE},
+        {type_shrt, "-32768",      0, 6, /* -32768 */ 1, IOSTATE_eofbit,  6, 6,  FALSE},
+        {type_shrt, "-32769",      0, 6, /* -32768 */ 1, IOSTATE_faileof, 6, 6,  FALSE},
+        {type_shrt, "-2147483648", 0, 6, /* -32768 */ 1, IOSTATE_faileof, 6, 11, FALSE},
+        /* unsigned short */
+        {type_ushrt, "65535",          0, 6, /* 65535 */ 0, IOSTATE_eofbit,  6, 5,  FALSE},
+        {type_ushrt, "65536",          0, 6, /* 65535 */ 0, IOSTATE_faileof, 6, 5,  FALSE},
+        {type_ushrt, "12345678",       0, 6, /* 65535 */ 0, IOSTATE_faileof, 6, 8,  FALSE},
+        {type_ushrt, "2147483648",     0, 6, /* 65535 */ 0, IOSTATE_faileof, 6, 10, FALSE},
+        {type_ushrt, "4294967296",     0, 6, /* 65535 */ 0, IOSTATE_faileof, 6, 10, FALSE},
+        {type_ushrt, "99999999999999", 0, 6, /* 65535 */ 0, IOSTATE_faileof, 6, 14, FALSE},
+        {type_ushrt, "-1",             0, 6, /* 65535 */ 0, IOSTATE_eofbit,  6, 2,  TRUE},
+        {type_ushrt, "-2",             0, 6, /* 65534 */ 1, IOSTATE_eofbit,  6, 2,  FALSE},
+        {type_ushrt, "-32768",         0, 6, /* 32768 */ 2, IOSTATE_eofbit,  6, 6,  FALSE},
+        {type_ushrt, "-32769",         0, 6, /* 65535 */ 0, IOSTATE_faileof, 6, 6,  FALSE},
+        {type_ushrt, "-2147483648",    0, 6, /* 65535 */ 0, IOSTATE_faileof, 6, 11, FALSE},
+        /* int */
+        {type_int, "",            FLAGS_skipws, 6, /* 123456789 */   0, IOSTATE_faileof, 6, 0,  FALSE},
+        {type_int, " 0",          FLAGS_skipws, 6, /* 0 */           1, IOSTATE_eofbit,  6, 2,  FALSE},
+        {type_int, " 0",          0,            6, /* 0 */           1, IOSTATE_failbit, 6, 0,  FALSE},
+        {type_int, "+1 ",         0,            6, /* 1 */           2, IOSTATE_goodbit, 6, 2,  FALSE},
+        {type_int, "1L",          0,            6, /* 1 */           2, IOSTATE_goodbit, 6, 1,  FALSE},
+        {type_int, "-500.0",      0,            6, /* -500 */        3, IOSTATE_goodbit, 6, 4,  FALSE},
+        {type_int, "0x8000",      0,            6, /* 0x8000 */      4, IOSTATE_eofbit,  6, 6,  FALSE},
+        {type_int, "0xtest",      0,            6, /* 0 */           1, IOSTATE_failbit, 6, 0,  FALSE},
+        {type_int, "0test",       0,            6, /* 0 */           1, IOSTATE_goodbit, 6, 1,  FALSE},
+        {type_int, "0x7ffffffe",  0,            6, /* 2147483646 */  5, IOSTATE_eofbit,  6, 10, FALSE},
+        {type_int, "0x7fffffff",  0,            6, /* 2147483647 */  6, IOSTATE_eofbit,  6, 10, FALSE},
+        {type_int, "0x80000000",  0,            6, /* 2147483647 */  6, IOSTATE_eofbit,  6, 10, FALSE},
+        {type_int, "0xdeadbeef",  0,            6, /* 2147483647 */  6, IOSTATE_eofbit,  6, 10, FALSE},
+        {type_int, "2147483648",  0,            6, /* 2147483647 */  6, IOSTATE_eofbit,  6, 10, FALSE},
+        {type_int, "4294967295",  0,            6, /* 2147483647 */  6, IOSTATE_eofbit,  6, 10, FALSE},
+        {type_int, "-2147483647", 0,            6, /* -2147483647 */ 7, IOSTATE_eofbit,  6, 11, FALSE},
+        {type_int, "-2147483648", 0,            6, /* -2147483648 */ 8, IOSTATE_eofbit,  6, 11, FALSE},
+        {type_int, "-2147483649", 0,            6, /* -2147483648 */ 8, IOSTATE_eofbit,  6, 11, FALSE},
+        {type_int, "-1f",         FLAGS_dec,    6, /* -1 */          9, IOSTATE_goodbit, 6, 2,  FALSE},
+        /* unsigned int */
+        {type_uint, "4294967295",     0, 6, /* 4294967295 */ 0, IOSTATE_eofbit,  6, 10, TRUE},
+        {type_uint, "4294967296",     0, 6, /* 4294967295 */ 0, IOSTATE_faileof, 6, 10, FALSE},
+        {type_uint, "99999999999999", 0, 6, /* 4294967295 */ 0, IOSTATE_faileof, 6, 14, FALSE},
+        {type_uint, "-1",             0, 6, /* 4294967295 */ 0, IOSTATE_eofbit,  6, 2,  TRUE},
+        {type_uint, "-2",             0, 6, /* 4294967294 */ 1, IOSTATE_eofbit,  6, 2,  FALSE},
+        {type_uint, "-2147483648",    0, 6, /* 2147483648 */ 2, IOSTATE_eofbit,  6, 11, FALSE},
+        {type_uint, "-4294967295",    0, 6, /* 1 */          3, IOSTATE_eofbit,  6, 11, FALSE},
+        {type_uint, "-9999999999999", 0, 6, /* 1 */          3, IOSTATE_eofbit,  6, 14, FALSE},
+        /* long */
+        {type_long, "2147483647",     0, 6, /* 2147483647 */  0, IOSTATE_eofbit,  6, 10, TRUE},
+        {type_long, "2147483648",     0, 6, /* 2147483647 */  0, IOSTATE_faileof, 6, 10, FALSE},
+        {type_long, "4294967295",     0, 6, /* 2147483647 */  0, IOSTATE_faileof, 6, 10, FALSE},
+        {type_long, "-2147483648",    0, 6, /* -2147483648 */ 1, IOSTATE_eofbit,  6, 11, TRUE},
+        {type_long, "-2147483649",    0, 6, /* -2147483648 */ 1, IOSTATE_faileof, 6, 11, FALSE},
+        {type_long, "-9999999999999", 0, 6, /* -2147483648 */ 1, IOSTATE_faileof, 6, 14, FALSE},
+        /* unsigned long */
+        {type_ulong, "4294967295",     0, 6, /* 4294967295 */ 0, IOSTATE_eofbit,  6, 10, TRUE},
+        {type_ulong, "4294967296",     0, 6, /* 4294967295 */ 0, IOSTATE_faileof, 6, 10, FALSE},
+        {type_ulong, "99999999999999", 0, 6, /* 4294967295 */ 0, IOSTATE_faileof, 6, 14, FALSE},
+        {type_ulong, "-1",             0, 6, /* 4294967295 */ 0, IOSTATE_eofbit,  6, 2,  TRUE},
+        {type_ulong, "-2",             0, 6, /* 4294967294 */ 1, IOSTATE_eofbit,  6, 2,  FALSE},
+        {type_ulong, "-2147483648",    0, 6, /* 2147483648 */ 2, IOSTATE_eofbit,  6, 11, FALSE},
+        {type_ulong, "-4294967295",    0, 6, /* 1 */          3, IOSTATE_eofbit,  6, 11, FALSE},
+        {type_ulong, "-9999999999999", 0, 6, /* 1 */          3, IOSTATE_eofbit,  6, 14, FALSE},
     };
 
     pssb = call_func2(p_strstreambuf_dynamic_ctor, &ssb, 64);
@@ -4934,6 +5024,42 @@ static void test_istream_read(void)
             ok(!strcmp(st, str_out[tests[i].expected_val]), "Test %d: expected %s got %s\n", i,
                 str_out[tests[i].expected_val], st);
             break;
+        case type_shrt:
+            s = 12345;
+            pis = call_func2(p_istream_read_short, &is, &s);
+            ok(s == short_out[tests[i].expected_val], "Test %d: expected %hd got %hd\n", i,
+                short_out[tests[i].expected_val], s);
+            break;
+        case type_ushrt:
+            us = 12345u;
+            pis = call_func2(p_istream_read_unsigned_short, &is, &us);
+            ok(us == ushort_out[tests[i].expected_val], "Test %d: expected %hu got %hu\n", i,
+                ushort_out[tests[i].expected_val], us);
+            break;
+        case type_int:
+            n = 123456789;
+            pis = call_func2(p_istream_read_int, &is, &n);
+            ok(n == int_out[tests[i].expected_val], "Test %d: expected %d got %d\n", i,
+                int_out[tests[i].expected_val], n);
+            break;
+        case type_uint:
+            un = 123456789u;
+            pis = call_func2(p_istream_read_unsigned_int, &is, &un);
+            ok(un == uint_out[tests[i].expected_val], "Test %d: expected %u got %u\n", i,
+                uint_out[tests[i].expected_val], un);
+            break;
+        case type_long:
+            l = 123456789l;
+            pis = call_func2(p_istream_read_long, &is, &l);
+            ok(l == long_out[tests[i].expected_val], "Test %d: expected %d got %d\n", i,
+                long_out[tests[i].expected_val], l);
+            break;
+        case type_ulong:
+            ul = 123456789ul;
+            pis = call_func2(p_istream_read_unsigned_long, &is, &ul);
+            ok(ul == ulong_out[tests[i].expected_val], "Test %d: expected %u got %u\n", i,
+                ulong_out[tests[i].expected_val], ul);
+            break;
         }
 
         ok(pis == &is, "Test %d: wrong return, expected %p got %p\n", i, &is, pis);
-- 
2.7.4




More information about the wine-patches mailing list