[v2 5/6] msvcirt: Implement istream::operator>> for floats.

Iván Matellanes matellanesivan at gmail.com
Tue Aug 2 06:37:50 CDT 2016


From: Iván Matellanes <matellanes.ivan at gmail.com>

Signed-off-by: Iván Matellanes <matellanesivan at gmail.com>
---
 dlls/msvcirt/msvcirt.c       | 41 ++++++++++++++++++++++----
 dlls/msvcirt/tests/msvcirt.c | 69 +++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 103 insertions(+), 7 deletions(-)

diff --git a/dlls/msvcirt/msvcirt.c b/dlls/msvcirt/msvcirt.c
index 608aeed..6964809 100644
--- a/dlls/msvcirt/msvcirt.c
+++ b/dlls/msvcirt/msvcirt.c
@@ -21,6 +21,7 @@
 
 #include <errno.h>
 #include <fcntl.h>
+#include <float.h>
 #include <io.h>
 #include <limits.h>
 #include <share.h>
@@ -3659,13 +3660,43 @@ istream* __thiscall istream_read_unsigned_long(istream *this, ULONG *p)
     return istream_internal_read_unsigned_integer(this, p, 2);
 }
 
+static istream* istream_internal_read_float(istream *this, void *p, int size)
+{
+    /* size: 0 => float, 1 => double, 2 => long double */
+    const int max_chars[3] = {20, 28, 32}; /* character count is limited on Windows */
+    char buffer[32]; 
+    double d;
+
+    TRACE("(%p %p %d)\n", this, p, size);
+
+    if (istream_ipfx(this, 0)) {
+        if (istream_getdouble(this, buffer, max_chars[size]) > 0) {
+            d = strtod(buffer, NULL);
+            if (size == 0) {
+                /* check whether the value fits in the output var */
+                if (d > FLT_MAX)
+                    d = FLT_MAX;
+                else if (d < -FLT_MAX)
+                    d = -FLT_MAX;
+                else if (d > 0 && d < FLT_MIN)
+                    d = FLT_MIN;
+                else if (d < 0 && d > -FLT_MIN)
+                    d = -FLT_MIN;
+                *((float*) p) = d;
+            } else
+                *((double*) p) = d;
+        }
+        istream_isfx(this);
+    }
+    return this;
+}
+
 /* ??5istream@@QAEAAV0 at AAM@Z */
 /* ??5istream@@QEAAAEAV0 at AEAM@Z */
 DEFINE_THISCALL_WRAPPER(istream_read_float, 8)
 istream* __thiscall istream_read_float(istream *this, float *f)
 {
-    FIXME("(%p %p) stub\n", this, f);
-    return this;
+    return istream_internal_read_float(this, f, 0);
 }
 
 /* ??5istream@@QAEAAV0 at AAN@Z */
@@ -3673,8 +3704,7 @@ istream* __thiscall istream_read_float(istream *this, float *f)
 DEFINE_THISCALL_WRAPPER(istream_read_double, 8)
 istream* __thiscall istream_read_double(istream *this, double *d)
 {
-    FIXME("(%p %p) stub\n", this, d);
-    return this;
+    return istream_internal_read_float(this, d, 1);
 }
 
 /* ??5istream@@QAEAAV0 at AAO@Z */
@@ -3682,8 +3712,7 @@ istream* __thiscall istream_read_double(istream *this, double *d)
 DEFINE_THISCALL_WRAPPER(istream_read_long_double, 8)
 istream* __thiscall istream_read_long_double(istream *this, double *ld)
 {
-    FIXME("(%p %p) stub\n", this, ld);
-    return this;
+    return istream_internal_read_float(this, ld, 2);
 }
 
 /* ??5istream@@QAEAAV0 at PAVstreambuf@@@Z */
diff --git a/dlls/msvcirt/tests/msvcirt.c b/dlls/msvcirt/tests/msvcirt.c
index e0e5f91..7e0f33c 100644
--- a/dlls/msvcirt/tests/msvcirt.c
+++ b/dlls/msvcirt/tests/msvcirt.c
@@ -335,6 +335,9 @@ 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*);
+static istream* (*__thiscall p_istream_read_float)(istream*, float*);
+static istream* (*__thiscall p_istream_read_double)(istream*, double*);
+static istream* (*__thiscall p_istream_read_long_double)(istream*, double*);
 
 /* Emulate a __thiscall */
 #ifdef __i386__
@@ -558,6 +561,9 @@ static BOOL init(void)
         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");
+        SET(p_istream_read_float, "??5istream@@QEAAAEAV0 at AEAM@Z");
+        SET(p_istream_read_double, "??5istream@@QEAAAEAV0 at AEAN@Z");
+        SET(p_istream_read_long_double, "??5istream@@QEAAAEAV0 at AEAO@Z");
     } else {
         p_operator_new = (void*)GetProcAddress(msvcrt, "??2 at YAPAXI@Z");
         p_operator_delete = (void*)GetProcAddress(msvcrt, "??3 at YAXPAX@Z");
@@ -703,6 +709,9 @@ static BOOL init(void)
         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_istream_read_float, "??5istream@@QAEAAV0 at AAM@Z");
+        SET(p_istream_read_double, "??5istream@@QAEAAV0 at AAN@Z");
+        SET(p_istream_read_long_double, "??5istream@@QAEAAV0 at AAO@Z");
     }
     SET(p_ios_static_lock, "?x_lockc at ios@@0U_CRT_CRITICAL_SECTION@@A");
     SET(p_ios_lockc, "?lockc at ios@@KAXXZ");
@@ -4892,9 +4901,11 @@ static void test_istream_read(void)
     unsigned un, uint_out[] = {4294967295u, 4294967294u, 2147483648u, 1u};
     LONG l, long_out[] = {2147483647l, -2147483647l-1};
     ULONG ul, ulong_out[] = {4294967295ul, 4294967294ul, 2147483648ul, 1ul};
+    float f, float_out[] = {123.456f, 0.0f, 1.0f, 0.1f, -1.0f, -0.1f, FLT_MIN, -FLT_MIN, FLT_MAX, -FLT_MAX};
+    double d, double_out[] = {1.0, 0.1, 0.0, INFINITY, -INFINITY};
     struct istream_read_test {
         enum { type_chr, type_str, type_shrt, type_ushrt, type_int, type_uint,
-            type_long, type_ulong } type;
+            type_long, type_ulong, type_flt, type_dbl, type_ldbl } type;
         const char *stream_content;
         ios_flags flags;
         int width;
@@ -4992,6 +5003,44 @@ static void test_istream_read(void)
         {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},
+        /* float */
+        {type_flt, "",                      FLAGS_skipws, 6, /* 123.456 */  0, IOSTATE_faileof, 6, 0,  FALSE},
+        {type_flt, "",                      0,            6, /* 123.456 */  0, IOSTATE_faileof, 6, 0,  FALSE},
+        {type_flt, " 0",                    0,            6, /* 123.456 */  0, IOSTATE_failbit, 6, 0,  FALSE},
+        {type_flt, " 0",                    FLAGS_skipws, 6, /* 0.0 */      1, IOSTATE_eofbit,  6, 2,  FALSE},
+        {type_flt, "-0 ",                   0,            6, /* 0.0 */      1, IOSTATE_goodbit, 6, 2,  FALSE},
+        {type_flt, "+1.0",                  0,            6, /* 1.0 */      2, IOSTATE_eofbit,  6, 4,  FALSE},
+        {type_flt, "1.#INF",                0,            6, /* 1.0 */      2, IOSTATE_goodbit, 6, 2,  FALSE},
+        {type_flt, "0.100000000000000e1",   0,            6, /* 1.0 */      2, IOSTATE_eofbit,  6, 19, FALSE},
+/* crashes on xp
+        {type_flt, "0.1000000000000000e1",  0,            6,    0.1         3, IOSTATE_failbit, 6, 20, FALSE}, */
+        {type_flt, "0.10000000000000000e1", 0,            6, /* 0.1 */      3, IOSTATE_failbit, 6, 20, TRUE},
+        {type_flt, "-0.10000000000000e1",   0,            6, /* -1.0 */     4, IOSTATE_eofbit,  6, 19, FALSE},
+/* crashes on xp
+        {type_flt, "-0.100000000000000e1 ", 0,            6,    -0.1        5, IOSTATE_failbit, 6, 20, FALSE}, */
+        {type_flt, "-0.1000000000000000e1", 0,            6, /* -0.1 */     5, IOSTATE_failbit, 6, 20, TRUE},
+        {type_flt, "5.1691126e-77",         0,            6, /* FLT_MIN */  6, IOSTATE_eofbit,  6, 13, FALSE},
+        {type_flt, "-2.49873e-41f",         0,            6, /* -FLT_MIN */ 7, IOSTATE_goodbit, 6, 12, FALSE},
+        {type_flt, "1.23456789e1234",       0,            6, /* FLT_MAX */  8, IOSTATE_eofbit,  6, 15, FALSE},
+        {type_flt, "-1.23456789e1234",      0,            6, /* -FLT_MAX */ 9, IOSTATE_eofbit,  6, 16, FALSE},
+        /* double */
+        {type_dbl, "0.10000000000000000000000e1",   0, 6, /* 1.0 */  0, IOSTATE_eofbit,  6, 27, FALSE},
+/* crashes on xp
+        {type_dbl, "0.100000000000000000000000e1",  0, 6,    0.1     1, IOSTATE_failbit, 6, 28, FALSE}, */
+        {type_dbl, "0.1000000000000000000000000e1", 0, 6, /* 0.1 */  1, IOSTATE_failbit, 6, 28, TRUE},
+        {type_dbl, "3.698124698114778e-6228",       0, 6, /* 0.0 */  2, IOSTATE_eofbit,  6, 23, FALSE},
+        {type_dbl, "-3.698124698114778e-6228",      0, 6, /* 0.0 */  2, IOSTATE_eofbit,  6, 24, FALSE},
+        {type_dbl, "3.698124698114778e6228",        0, 6, /* INF */  3, IOSTATE_eofbit,  6, 22, FALSE},
+        {type_dbl, "-3.698124698114778e6228A",      0, 6, /* -INF */ 4, IOSTATE_goodbit, 6, 23, FALSE},
+        /* long double */
+        {type_ldbl, "0.100000000000000000000000000e1",   0, 6, /* 1.0 */  0, IOSTATE_eofbit,  6, 31, FALSE},
+/* crashes on xp
+        {type_ldbl, "0.1000000000000000000000000000e1",  0, 6,    0.1     1, IOSTATE_failbit, 6, 32, FALSE}, */
+        {type_ldbl, "0.10000000000000000000000000000e1", 0, 6, /* 0.1 */  1, IOSTATE_failbit, 6, 32, TRUE},
+        {type_ldbl, "1.69781699841e-1475",               0, 6, /* 0.0 */  2, IOSTATE_eofbit,  6, 19, FALSE},
+        {type_ldbl, "-1.69781699841e-1475l",             0, 6, /* 0.0 */  2, IOSTATE_goodbit, 6, 20, FALSE},
+        {type_ldbl, "1.69781699841e1475",                0, 6, /* INF */  3, IOSTATE_eofbit,  6, 18, FALSE},
+        {type_ldbl, "-1.69781699841e1475",               0, 6, /* -INF */ 4, IOSTATE_eofbit,  6, 19, FALSE},
     };
 
     pssb = call_func2(p_strstreambuf_dynamic_ctor, &ssb, 64);
@@ -5060,6 +5109,24 @@ static void test_istream_read(void)
             ok(ul == ulong_out[tests[i].expected_val], "Test %d: expected %u got %u\n", i,
                 ulong_out[tests[i].expected_val], ul);
             break;
+        case type_flt:
+            f = 123.456f;
+            pis = call_func2(p_istream_read_float, &is, &f);
+            ok(f == float_out[tests[i].expected_val], "Test %d: expected %f got %f\n", i,
+                float_out[tests[i].expected_val], f);
+            break;
+        case type_dbl:
+            d = 123.456;
+            pis = call_func2(p_istream_read_double, &is, &d);
+            ok(d == double_out[tests[i].expected_val], "Test %d: expected %f got %f\n", i,
+                double_out[tests[i].expected_val], d);
+            break;
+        case type_ldbl:
+            d = 123.456;
+            pis = call_func2(p_istream_read_long_double, &is, &d);
+            ok(d == double_out[tests[i].expected_val], "Test %d: expected %f got %f\n", i,
+                double_out[tests[i].expected_val], d);
+            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