[5/6] msvcirt: Implement istream::operator>> for floats.
Iván Matellanes
matellanesivan at gmail.com
Mon Aug 1 05:40:42 CDT 2016
Signed-off-by: Iván Matellanes <matellanes.ivan 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 fdb975a..0de96c5 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, -2147483648l};
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