[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