[v2 4/7] msvcirt: Implement ostream::operator<< for floats
Iván Matellanes
matellanesivan at gmail.com
Wed Jun 22 04:53:05 CDT 2016
Signed-off-by: Iván Matellanes <matellanes.ivan at gmail.com>
---
dlls/msvcirt/msvcirt.c | 47 +++++++++++++++++++++---
dlls/msvcirt/tests/msvcirt.c | 86 ++++++++++++++++++++++++++++++++++++++++++--
2 files changed, 127 insertions(+), 6 deletions(-)
diff --git a/dlls/msvcirt/msvcirt.c b/dlls/msvcirt/msvcirt.c
index 9988944..7d0696a 100644
--- a/dlls/msvcirt/msvcirt.c
+++ b/dlls/msvcirt/msvcirt.c
@@ -2631,6 +2631,47 @@ static ostream* ostream_internal_print_integer(ostream *ostr, int n, BOOL unsig,
return ostr;
}
+static ostream* ostream_internal_print_float(ostream *ostr, double d, BOOL dbl)
+{
+ ios *base = ostream_get_ios(ostr);
+ char prefix_str[2] = {0}, number_str[24], sprintf_fmt[6] = {'%','.','*','f',0};
+ int prec, max_prec = dbl ? 15 : 6;
+ int str_length = 1; /* null end char */
+
+ TRACE("(%p %lf %d)\n", ostr, d, dbl);
+
+ if (ostream_opfx(ostr)) {
+ if ((base->flags & FLAGS_showpos) && d > 0) {
+ prefix_str[0] = '+';
+ str_length++; /* plus sign */
+ }
+ if ((base->flags & (FLAGS_scientific|FLAGS_fixed)) == FLAGS_scientific)
+ sprintf_fmt[3] = (base->flags & FLAGS_uppercase) ? 'E' : 'e';
+ else if ((base->flags & (FLAGS_scientific|FLAGS_fixed)) != FLAGS_fixed)
+ sprintf_fmt[3] = (base->flags & FLAGS_uppercase) ? 'G' : 'g';
+ if (base->flags & FLAGS_showpoint) {
+ sprintf_fmt[4] = sprintf_fmt[3];
+ sprintf_fmt[3] = sprintf_fmt[2];
+ sprintf_fmt[2] = sprintf_fmt[1];
+ sprintf_fmt[1] = '#';
+ }
+
+ prec = (base->precision >= 0 && base->precision <= max_prec) ? base->precision : max_prec;
+ str_length += _scprintf(sprintf_fmt, prec, d); /* number representation */
+ if (str_length > 24) {
+ /* too long to output */
+ ostream_writepad(ostr, "", "");
+ } else {
+ if (sprintf(number_str, sprintf_fmt, prec, d) > 0)
+ ostream_writepad(ostr, prefix_str, number_str);
+ else
+ base->state |= IOSTATE_failbit;
+ }
+ ostream_osfx(ostr);
+ }
+ return ostr;
+}
+
/* ??6ostream@@QAEAAV0 at C@Z */
/* ??6ostream@@QEAAAEAV0 at C@Z */
/* ??6ostream@@QAEAAV0 at D@Z */
@@ -2721,8 +2762,7 @@ ostream* __thiscall ostream_print_unsigned_int(ostream *this, unsigned int n)
DEFINE_THISCALL_WRAPPER(ostream_print_float, 8)
ostream* __thiscall ostream_print_float(ostream *this, float f)
{
- FIXME("(%p %f) stub\n", this, f);
- return this;
+ return ostream_internal_print_float(this, f, FALSE);
}
/* ??6ostream@@QAEAAV0 at N@Z */
@@ -2732,8 +2772,7 @@ ostream* __thiscall ostream_print_float(ostream *this, float f)
DEFINE_THISCALL_WRAPPER(ostream_print_double, 12)
ostream* __thiscall ostream_print_double(ostream *this, double d)
{
- FIXME("(%p %lf) stub\n", this, d);
- return this;
+ return ostream_internal_print_float(this, d, TRUE);
}
/* ??6ostream@@QAEAAV0 at PBX@Z */
diff --git a/dlls/msvcirt/tests/msvcirt.c b/dlls/msvcirt/tests/msvcirt.c
index 6a89519..16f5bc3 100644
--- a/dlls/msvcirt/tests/msvcirt.c
+++ b/dlls/msvcirt/tests/msvcirt.c
@@ -17,6 +17,7 @@
*/
#include <fcntl.h>
+#include <float.h>
#include <io.h>
#include <stdio.h>
#include <windef.h>
@@ -273,6 +274,8 @@ static ostream* (*__thiscall p_ostream_writepad)(ostream*, const char*, const ch
static ostream* (*__thiscall p_ostream_print_char)(ostream*, char);
static ostream* (*__thiscall p_ostream_print_str)(ostream*, const char*);
static ostream* (*__thiscall p_ostream_print_int)(ostream*, int);
+static ostream* (*__thiscall p_ostream_print_float)(ostream*, float);
+static ostream* (*__thiscall p_ostream_print_double)(ostream*, double);
/* Emulate a __thiscall */
#ifdef __i386__
@@ -295,6 +298,8 @@ static void * (WINAPI *call_thiscall_func4)( void *func, void *this, const void
const void *c );
static void * (WINAPI *call_thiscall_func5)( void *func, void *this, const void *a, const void *b,
const void *c, const void *d );
+static void * (WINAPI *call_thiscall_func2_ptr_dbl)( void *func, void *this, double a );
+static void * (WINAPI *call_thiscall_func2_ptr_flt)( void *func, void *this, float a );
static void init_thiscall_thunk(void)
{
@@ -310,6 +315,8 @@ static void init_thiscall_thunk(void)
call_thiscall_func3 = (void *)thunk;
call_thiscall_func4 = (void *)thunk;
call_thiscall_func5 = (void *)thunk;
+ call_thiscall_func2_ptr_dbl = (void *)thunk;
+ call_thiscall_func2_ptr_flt = (void *)thunk;
}
#define call_func1(func,_this) call_thiscall_func1(func,_this)
@@ -319,6 +326,8 @@ static void init_thiscall_thunk(void)
(const void*)(c))
#define call_func5(func,_this,a,b,c,d) call_thiscall_func5(func,_this,(const void*)(a),(const void*)(b), \
(const void*)(c), (const void *)(d))
+#define call_func2_ptr_dbl(func,_this,a) call_thiscall_func2_ptr_dbl(func,_this,a)
+#define call_func2_ptr_flt(func,_this,a) call_thiscall_func2_ptr_flt(func,_this,a)
#else
@@ -328,6 +337,8 @@ static void init_thiscall_thunk(void)
#define call_func3(func,_this,a,b) func(_this,a,b)
#define call_func4(func,_this,a,b,c) func(_this,a,b,c)
#define call_func5(func,_this,a,b,c,d) func(_this,a,b,c,d)
+#define call_func2_ptr_dbl call_func2
+#define call_func2_ptr_flt call_func2
#endif /* __i386__ */
@@ -450,6 +461,8 @@ static BOOL init(void)
SET(p_ostream_print_char, "??6ostream@@QEAAAEAV0 at D@Z");
SET(p_ostream_print_str, "??6ostream@@QEAAAEAV0 at PEBD@Z");
SET(p_ostream_print_int, "??6ostream@@QEAAAEAV0 at H@Z");
+ SET(p_ostream_print_float, "??6ostream@@QEAAAEAV0 at M@Z");
+ SET(p_ostream_print_double, "??6ostream@@QEAAAEAV0 at N@Z");
} else {
p_operator_new = (void*)GetProcAddress(msvcrt, "??2 at YAPAXI@Z");
p_operator_delete = (void*)GetProcAddress(msvcrt, "??3 at YAXPAX@Z");
@@ -557,6 +570,8 @@ static BOOL init(void)
SET(p_ostream_print_char, "??6ostream@@QAEAAV0 at D@Z");
SET(p_ostream_print_str, "??6ostream@@QAEAAV0 at PBD@Z");
SET(p_ostream_print_int, "??6ostream@@QAEAAV0 at H@Z");
+ SET(p_ostream_print_float, "??6ostream@@QAEAAV0 at M@Z");
+ SET(p_ostream_print_double, "??6ostream@@QAEAAV0 at N@Z");
}
SET(p_ios_static_lock, "?x_lockc at ios@@0U_CRT_CRITICAL_SECTION@@A");
SET(p_ios_lockc, "?lockc at ios@@KAXXZ");
@@ -3021,8 +3036,12 @@ static void test_ostream_print(void)
char param_char[] = {'a', '9', 'e'};
const char* param_str[] = {"Test", "800", "3.14159", " Test"};
int param_int[] = {0, 7, 10, 24 ,55, 1024, 1023, 65536, 2147483647, 2147483648, 4294967295, -20};
+ float param_float[] = {1.0f, 0.0f, 4.25f, 3.999f, 12.0005f, 15.33582f, 15.0f, 15.22f, 21.123f, 0.1f,
+ 13.14159f, 0.00013f, 0.000013f, 1.0f / 0.0f, -1.0f / 0.0f, 0.0f / 0.0f};
+ double param_double[] = {1.0, 3.141592653589793238, 314.1592653589793238, 314.159265358979,
+ 1231314.269811862199, 9.961472e6, DBL_MAX};
struct ostream_print_test {
- enum { CHAR, STR, INT } type;
+ enum { CHAR, STR, INT, FLOAT, DOUBLE } type;
int param_index;
ios_io_state state;
ios_flags flags;
@@ -3087,7 +3106,66 @@ static void test_ostream_print(void)
{INT, /* 4294967295 */ 10, IOSTATE_goodbit, FLAGS_internal, 6, ' ', 8, " -1", IOSTATE_goodbit},
{INT, /* -20 */ 11, IOSTATE_goodbit, FLAGS_internal|FLAGS_oct|FLAGS_showbase, 6, ' ', 8, "037777777754", IOSTATE_goodbit},
{INT, /* -20 */ 11, IOSTATE_goodbit, FLAGS_dec|FLAGS_showpos, 6, ' ', 0, "-20", IOSTATE_goodbit},
- {INT, /* 0 */ 0, IOSTATE_goodbit, FLAGS_internal|FLAGS_showpos, 6, ' ', 8, " 0", IOSTATE_goodbit}
+ {INT, /* 0 */ 0, IOSTATE_goodbit, FLAGS_internal|FLAGS_showpos, 6, ' ', 8, " 0", IOSTATE_goodbit},
+ /* float */
+ {FLOAT, /* 1.0f */ 0, IOSTATE_badbit, 0, 6, ' ', 0, "", IOSTATE_badbit|IOSTATE_failbit},
+ {FLOAT, /* 1.0f */ 0, IOSTATE_eofbit, 0, 6, ' ', 0, "", IOSTATE_eofbit|IOSTATE_failbit},
+ {FLOAT, /* 1.0f */ 0, IOSTATE_goodbit, 0, 6, ' ', 0, "1", IOSTATE_goodbit},
+ {FLOAT, /* 0.0f */ 1, IOSTATE_goodbit, 0, 6, ' ', 0, "0", IOSTATE_goodbit},
+ {FLOAT, /* 4.25f */ 2, IOSTATE_goodbit, 0, 6, ' ', 0, "4.25", IOSTATE_goodbit},
+ {FLOAT, /* 3.999f */ 3, IOSTATE_goodbit, 0, 6, ' ', 0, "3.999", IOSTATE_goodbit},
+ {FLOAT, /* 3.999f */ 3, IOSTATE_goodbit, 0, 3, ' ', 0, "4", IOSTATE_goodbit},
+ {FLOAT, /* 12.0005f */ 4, IOSTATE_goodbit, 0, 6, ' ', 0, "12.0005", IOSTATE_goodbit},
+ {FLOAT, /* 12.0005f */ 4, IOSTATE_goodbit, 0, 5, ' ', 0, "12", IOSTATE_goodbit},
+ {FLOAT, /* 15.33582f */ 5, IOSTATE_goodbit, 0, 4, ' ', 0, "15.34", IOSTATE_goodbit},
+ {FLOAT, /* 15.0f */ 6, IOSTATE_goodbit, FLAGS_internal|FLAGS_hex|FLAGS_showbase, 6, ' ', 4, " 15", IOSTATE_goodbit},
+ {FLOAT, /* 15.22f */ 7, IOSTATE_goodbit, FLAGS_left|FLAGS_hex|FLAGS_showbase, 3, ' ', 6, "15.2 ", IOSTATE_goodbit},
+ {FLOAT, /* 15.22 */ 7, IOSTATE_goodbit, FLAGS_internal, 3, 'x', 6, "xx15.2", IOSTATE_goodbit},
+ {FLOAT, /* 21.123f */ 8, IOSTATE_goodbit, FLAGS_showpoint, 9, ' ', 0, "21.1230", IOSTATE_goodbit},
+ {FLOAT, /* 21.123f */ 8, IOSTATE_goodbit, FLAGS_showpos, 9, ' ', 0, "+21.123", IOSTATE_goodbit},
+ {FLOAT, /* 21.123f */ 8, IOSTATE_goodbit, FLAGS_internal|FLAGS_showpos, 9, ' ', 8, "+ 21.123", IOSTATE_goodbit},
+ {FLOAT, /* 21.123f */ 8, IOSTATE_goodbit, FLAGS_showpos, 0, ' ', 0, "+2e+001", IOSTATE_goodbit},
+ {FLOAT, /* 21.123f */ 8, IOSTATE_goodbit, 0, 1, ' ', 0, "2e+001", IOSTATE_goodbit},
+ {FLOAT, /* 21.123f */ 8, IOSTATE_goodbit, FLAGS_showpos, 2, ' ', 0, "+21", IOSTATE_goodbit},
+ {FLOAT, /* 21.123f */ 8, IOSTATE_goodbit, 0, 4, ' ', 0, "21.12", IOSTATE_goodbit},
+ {FLOAT, /* 21.123f */ 8, IOSTATE_goodbit, FLAGS_scientific, 2, ' ', 0, "2.11e+001", IOSTATE_goodbit},
+ {FLOAT, /* 21.123f */ 8, IOSTATE_goodbit, FLAGS_scientific, 4, ' ', 0, "2.1123e+001", IOSTATE_goodbit},
+ {FLOAT, /* 21.123f */ 8, IOSTATE_goodbit, FLAGS_scientific, 6, ' ', 0, "2.112300e+001", IOSTATE_goodbit},
+ {FLOAT, /* 21.123f */ 8, IOSTATE_goodbit, FLAGS_scientific|FLAGS_uppercase, 2, ' ', 0, "2.11E+001", IOSTATE_goodbit},
+ {FLOAT, /* 21.123f */ 8, IOSTATE_goodbit, FLAGS_scientific|FLAGS_uppercase, 2, '*', 10, "*2.11E+001", IOSTATE_goodbit},
+ {FLOAT, /* 21.123f */ 8, IOSTATE_goodbit, FLAGS_fixed, 6, ' ', 0, "21.122999", IOSTATE_goodbit},
+ {FLOAT, /* 0.1f */ 9, IOSTATE_goodbit, FLAGS_fixed, 6, ' ', 0, "0.100000", IOSTATE_goodbit},
+ {FLOAT, /* 0.1f */ 9, IOSTATE_goodbit, FLAGS_scientific, 6, ' ', 0, "1.000000e-001", IOSTATE_goodbit},
+ {FLOAT, /* 13.14159f */ 10, IOSTATE_goodbit, FLAGS_fixed, 3, ' ', 0, "13.142", IOSTATE_goodbit},
+ {FLOAT, /* 13.14159f */ 10, IOSTATE_goodbit, FLAGS_fixed, 8, ' ', 0, "13.141590", IOSTATE_goodbit},
+ {FLOAT, /* 13.14159f */ 10, IOSTATE_goodbit, FLAGS_fixed|FLAGS_showpoint, 8, ' ', 0, "13.141590", IOSTATE_goodbit},
+ {FLOAT, /* 13.14159f */ 10, IOSTATE_goodbit, FLAGS_scientific|FLAGS_fixed, 8, ' ', 0, "13.1416", IOSTATE_goodbit},
+ {FLOAT, /* 13.14159f */ 10, IOSTATE_goodbit, FLAGS_scientific|FLAGS_fixed, 2, ' ', 0, "13", IOSTATE_goodbit},
+ {FLOAT, /* 0.00013f */ 11, IOSTATE_goodbit, 0, -1, ' ', 0, "0.00013", IOSTATE_goodbit},
+ {FLOAT, /* 0.00013f */ 11, IOSTATE_goodbit, 0, -1, ' ', 0, "0.00013", IOSTATE_goodbit},
+ {FLOAT, /* 0.00013f */ 11, IOSTATE_goodbit, 0, -1, ' ', 0, "0.00013", IOSTATE_goodbit},
+ {FLOAT, /* 0.000013f */ 12, IOSTATE_goodbit, 0, 4, ' ', 0, "1.3e-005", IOSTATE_goodbit},
+ {FLOAT, /* 0.000013f */ 12, IOSTATE_goodbit, FLAGS_showpoint, 4, ' ', 0, "1.300e-005", IOSTATE_goodbit},
+ {FLOAT, /* 0.000013f */ 12, IOSTATE_goodbit, FLAGS_showpoint, 6, ' ', 0, "1.30000e-005", IOSTATE_goodbit},
+ {FLOAT, /* 1.0f / 0.0f */ 13, IOSTATE_goodbit, 0, 6, ' ', 0, "1.#INF", IOSTATE_goodbit},
+ {FLOAT, /* 1.0f / 0.0f */ 13, IOSTATE_goodbit, 0, 4, ' ', 0, "1.#IO", IOSTATE_goodbit},
+ {FLOAT, /* -1.0f / 0.0f */ 14, IOSTATE_goodbit, 0, 6, ' ', 0, "-1.#INF", IOSTATE_goodbit},
+ {FLOAT, /* 0.0f / 0.0f */ 15, IOSTATE_goodbit, 0, 6, ' ', 0, "-1.#IND", IOSTATE_goodbit},
+ /* double */
+ {DOUBLE, /* 1.0 */ 0, IOSTATE_goodbit, 0, 6, ' ', 0, "1", IOSTATE_goodbit},
+ {DOUBLE, /* 3.141592653589793238 */ 1, IOSTATE_goodbit, 0, 6, ' ', 0, "3.14159", IOSTATE_goodbit},
+ {DOUBLE, /* 3.141592653589793238 */ 1, IOSTATE_goodbit, 0, 9, ' ', 0, "3.14159265", IOSTATE_goodbit},
+ {DOUBLE, /* 3.141592653589793238 */ 1, IOSTATE_goodbit, 0, 12, ' ', 0, "3.14159265359", IOSTATE_goodbit},
+ {DOUBLE, /* 3.141592653589793238 */ 1, IOSTATE_goodbit, 0, 15, ' ', 0, "3.14159265358979", IOSTATE_goodbit},
+ {DOUBLE, /* 3.141592653589793238 */ 1, IOSTATE_goodbit, 0, 16, ' ', 0, "3.14159265358979", IOSTATE_goodbit},
+ {DOUBLE, /* 314.1592653589793238 */ 2, IOSTATE_goodbit, 0, 16, ' ', 0, "314.159265358979", IOSTATE_goodbit},
+ {DOUBLE, /* 3.141592653589793238 */ 1, IOSTATE_goodbit, FLAGS_scientific, 16, ' ', 0, "3.141592653589793e+000", IOSTATE_goodbit},
+ {DOUBLE, /* 314.1592653589793238 */ 2, IOSTATE_goodbit, FLAGS_scientific, 16, ' ', 0, "3.141592653589793e+002", IOSTATE_goodbit},
+ {DOUBLE, /* 3.141592653589793238 */ 1, IOSTATE_goodbit, FLAGS_fixed, -1, ' ', 0, "3.141592653589793", IOSTATE_goodbit},
+ {DOUBLE, /* 314.159265358979 */ 3, IOSTATE_goodbit, FLAGS_fixed, 12, ' ', 0, "314.159265358979", IOSTATE_goodbit},
+ {DOUBLE, /* 1231314.269811862199 */ 4, IOSTATE_goodbit, FLAGS_fixed, 10, ' ', 0, "1231314.2698118621", IOSTATE_goodbit},
+ {DOUBLE, /* 9.961472e6 */ 5, IOSTATE_goodbit, FLAGS_fixed, 500, ' ', 0, "9961472.000000000000000", IOSTATE_goodbit},
+ {DOUBLE, /* DBL_MAX */ 6, IOSTATE_goodbit, FLAGS_showpoint, 500, ' ', 0, "1.79769313486232e+308", IOSTATE_goodbit}
};
pssb = call_func1(p_strstreambuf_ctor, &ssb);
@@ -3110,6 +3188,10 @@ static void test_ostream_print(void)
pos = call_func2(p_ostream_print_str, &os, param_str[tests[i].param_index]); break;
case INT:
pos = call_func2(p_ostream_print_int, &os, param_int[tests[i].param_index]); break;
+ case FLOAT:
+ pos = call_func2_ptr_flt(p_ostream_print_float, &os, param_float[tests[i].param_index]); break;
+ case DOUBLE:
+ pos = call_func2_ptr_dbl(p_ostream_print_double, &os, param_double[tests[i].param_index]); break;
}
length = ssb.base.pptr - ssb.base.pbase;
--
2.7.4
More information about the wine-patches
mailing list