Hans Leidekker : webservices: Add support for writing double values.

Alexandre Julliard julliard at winehq.org
Fri Jul 8 10:02:05 CDT 2016


Module: wine
Branch: master
Commit: df4046a3705972978c408cf44ab0fd636e25e31d
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=df4046a3705972978c408cf44ab0fd636e25e31d

Author: Hans Leidekker <hans at codeweavers.com>
Date:   Fri Jul  8 10:20:30 2016 +0200

webservices: Add support for writing double values.

Signed-off-by: Hans Leidekker <hans at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/webservices/reader.c              |   8 +--
 dlls/webservices/tests/writer.c        | 113 +++++++++++++++++++++++++++++++++
 dlls/webservices/webservices_private.h |   2 +
 dlls/webservices/writer.c              | 100 +++++++++++++++++++++++++++++
 include/webservices.h                  |   5 ++
 5 files changed, 224 insertions(+), 4 deletions(-)

diff --git a/dlls/webservices/reader.c b/dlls/webservices/reader.c
index 9e33000..1a51257 100644
--- a/dlls/webservices/reader.c
+++ b/dlls/webservices/reader.c
@@ -2271,7 +2271,7 @@ static HRESULT str_to_uint64( const unsigned char *str, ULONG len, UINT64 max, U
 #if defined(__i386__) || defined(__x86_64__)
 
 #define RC_DOWN 0x100;
-static BOOL set_fp_rounding( unsigned short *save )
+BOOL set_fp_rounding( unsigned short *save )
 {
 #ifdef __GNUC__
     unsigned short fpword;
@@ -2286,7 +2286,7 @@ static BOOL set_fp_rounding( unsigned short *save )
     return FALSE;
 #endif
 }
-static void restore_fp_rounding( unsigned short fpword )
+void restore_fp_rounding( unsigned short fpword )
 {
 #ifdef __GNUC__
     __asm__ __volatile__( "fldcw %0" : : "m" (fpword) );
@@ -2295,12 +2295,12 @@ static void restore_fp_rounding( unsigned short fpword )
 #endif
 }
 #else
-static BOOL set_fp_rounding( unsigned short *save )
+BOOL set_fp_rounding( unsigned short *save )
 {
     FIXME( "not implemented\n" );
     return FALSE;
 }
-static void restore_fp_rounding( unsigned short fpword )
+void restore_fp_rounding( unsigned short fpword )
 {
     FIXME( "not implemented\n" );
 }
diff --git a/dlls/webservices/tests/writer.c b/dlls/webservices/tests/writer.c
index 9055021..d230cdd 100644
--- a/dlls/webservices/tests/writer.c
+++ b/dlls/webservices/tests/writer.c
@@ -21,6 +21,25 @@
 #include "webservices.h"
 #include "wine/test.h"
 
+#include <math.h>
+#ifndef INFINITY
+static inline float __port_infinity(void)
+{
+    static const unsigned __inf_bytes = 0x7f800000;
+    return *(const float *)&__inf_bytes;
+}
+#define INFINITY __port_infinity()
+#endif
+
+#ifndef NAN
+static inline float __port_nan(void)
+{
+    static const unsigned __nan_bytes = 0x7fc00000;
+    return *(const float *)&__nan_bytes;
+}
+#define NAN __port_nan()
+#endif
+
 static HRESULT set_output( WS_XML_WRITER *writer )
 {
     WS_XML_WRITER_TEXT_ENCODING encoding;
@@ -1871,6 +1890,99 @@ static void test_text_types(void)
     WsFreeWriter( writer );
 }
 
+static void test_double(void)
+{
+    WS_XML_STRING localname = {1, (BYTE *)"t"}, ns = {0, NULL};
+    static const struct
+    {
+        double      val;
+        const char *result;
+    }
+    tests[] =
+    {
+        {0.0, "<t>0</t>"},
+        {1.0, "<t>1</t>"},
+        {-1.0, "<t>-1</t>"},
+        {1.0000000000000001, "<t>1</t>"},
+        {1.0000000000000002, "<t>1.0000000000000002</t>"},
+        {1.0000000000000003, "<t>1.0000000000000002</t>"},
+        {1.0000000000000004, "<t>1.0000000000000004</t>"},
+        {100000000000000, "<t>100000000000000</t>"},
+        {1000000000000000, "<t>1E+15</t>"},
+        {0.1, "<t>0.1</t>"},
+        {0.01, "<t>1E-2</t>"},
+        {-0.1, "<t>-0.1</t>"},
+        {-0.01, "<t>-1E-2</t>"},
+        {1.7976931348623158e308, "<t>1.7976931348623157E+308</t>"},
+        {-1.7976931348623158e308, "<t>-1.7976931348623157E+308</t>"},
+    };
+    HRESULT hr;
+    WS_XML_WRITER *writer;
+    WS_XML_DOUBLE_TEXT text;
+    ULONG i;
+
+    hr = WsCreateWriter( NULL, 0, &writer, NULL ) ;
+    ok( hr == S_OK, "got %08x\n", hr );
+
+    text.text.textType = WS_XML_TEXT_TYPE_DOUBLE;
+    for (i = 0; i < sizeof(tests)/sizeof(tests[0]); i++)
+    {
+        hr = set_output( writer );
+        ok( hr == S_OK, "got %08x\n", hr );
+        hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
+        ok( hr == S_OK, "%u: got %08x\n", i, hr );
+
+        text.value = tests[i].val;
+        hr = WsWriteText( writer, &text.text, NULL );
+        ok( hr == S_OK, "%u: got %08x\n", i, hr );
+
+        hr = WsWriteEndElement( writer, NULL );
+        ok( hr == S_OK, "%u: got %08x\n", i, hr );
+        check_output( writer, tests[i].result, __LINE__ );
+    }
+
+    hr = set_output( writer );
+    ok( hr == S_OK, "got %08x\n", hr );
+    hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
+    ok( hr == S_OK, "got %08x\n", hr );
+
+    text.value = NAN;
+    hr = WsWriteText( writer, &text.text, NULL );
+    ok( hr == S_OK, "got %08x\n", hr );
+
+    hr = WsWriteEndElement( writer, NULL );
+    ok( hr == S_OK, "got %08x\n", hr );
+    check_output( writer, "<t>NaN</t>", __LINE__ );
+
+    hr = set_output( writer );
+    ok( hr == S_OK, "got %08x\n", hr );
+    hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
+    ok( hr == S_OK, "got %08x\n", hr );
+
+    text.value = INFINITY;
+    hr = WsWriteText( writer, &text.text, NULL );
+    ok( hr == S_OK, "got %08x\n", hr );
+
+    hr = WsWriteEndElement( writer, NULL );
+    ok( hr == S_OK, "got %08x\n", hr );
+    check_output( writer, "<t>INF</t>", __LINE__ );
+
+    hr = set_output( writer );
+    ok( hr == S_OK, "got %08x\n", hr );
+    hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
+    ok( hr == S_OK, "got %08x\n", hr );
+
+    text.value = -INFINITY;
+    hr = WsWriteText( writer, &text.text, NULL );
+    ok( hr == S_OK, "got %08x\n", hr );
+
+    hr = WsWriteEndElement( writer, NULL );
+    ok( hr == S_OK, "got %08x\n", hr );
+    check_output( writer, "<t>-INF</t>", __LINE__ );
+
+    WsFreeWriter( writer );
+}
+
 START_TEST(writer)
 {
     test_WsCreateWriter();
@@ -1896,4 +2008,5 @@ START_TEST(writer)
     test_WsWriteNode();
     test_WsCopyNode();
     test_text_types();
+    test_double();
 }
diff --git a/dlls/webservices/webservices_private.h b/dlls/webservices/webservices_private.h
index bad2dfb..26cba38 100644
--- a/dlls/webservices/webservices_private.h
+++ b/dlls/webservices/webservices_private.h
@@ -33,6 +33,8 @@ WS_XML_UTF8_TEXT *alloc_utf8_text( const unsigned char *, ULONG ) DECLSPEC_HIDDE
 HRESULT append_attribute( WS_XML_ELEMENT_NODE *, WS_XML_ATTRIBUTE * ) DECLSPEC_HIDDEN;
 void free_attribute( WS_XML_ATTRIBUTE * ) DECLSPEC_HIDDEN;
 WS_TYPE map_value_type( WS_VALUE_TYPE ) DECLSPEC_HIDDEN;
+BOOL set_fp_rounding( unsigned short * ) DECLSPEC_HIDDEN;
+void restore_fp_rounding( unsigned short ) DECLSPEC_HIDDEN;
 
 struct node
 {
diff --git a/dlls/webservices/writer.c b/dlls/webservices/writer.c
index 85a8973..48c7382 100644
--- a/dlls/webservices/writer.c
+++ b/dlls/webservices/writer.c
@@ -18,6 +18,7 @@
 
 #include <stdarg.h>
 #include <stdio.h>
+#include <math.h>
 
 #include "windef.h"
 #include "winbase.h"
@@ -1042,6 +1043,92 @@ static ULONG format_uint64( const UINT64 *ptr, unsigned char *buf )
     return wsprintfA( (char *)buf, "%I64u", *ptr );
 }
 
+static ULONG format_double( const double *ptr, unsigned char *buf )
+{
+    static const double precision = 0.0000000000000001;
+    unsigned char *p = buf;
+    double val = *ptr; /* FIXME: use long double */
+    int neg, mag, mag2, use_exp;
+
+    if (isnan( val ))
+    {
+        memcpy( buf, "NaN", 3 );
+        return 3;
+    }
+    if (isinf( val ))
+    {
+        if (val < 0)
+        {
+            memcpy( buf, "-INF", 4 );
+            return 4;
+        }
+        memcpy( buf, "INF", 3 );
+        return 3;
+    }
+    if (val == 0.0)
+    {
+        *p = '0';
+        return 1;
+    }
+
+    if ((neg = val < 0))
+    {
+        *p++ = '-';
+        val = -val;
+    }
+
+    mag = log10( val );
+    use_exp = (mag >= 15 || (neg && mag >= 1) || mag <= -1);
+    if (use_exp)
+    {
+        if (mag < 0) mag -= 1;
+        val = val / pow( 10.0, mag );
+        mag2 = mag;
+        mag = 0;
+    }
+    else if (mag < 1) mag = 0;
+
+    while (val > precision || mag >= 0)
+    {
+        double weight = pow( 10.0, mag );
+        if (weight > 0 && !isinf( weight ))
+        {
+            int digit = floor( val / weight );
+            val -= digit * weight;
+            *(p++) = '0' + digit;
+        }
+        if (!mag && val > 0) *(p++) = '.';
+        mag--;
+    }
+
+    if (use_exp)
+    {
+        int i, j;
+        *(p++) = 'E';
+        if (mag2 > 0) *(p++) = '+';
+        else
+        {
+            *(p++) = '-';
+            mag2 = -mag2;
+        }
+        mag = 0;
+        while (mag2 > 0)
+        {
+            *(p++) = '0' + mag2 % 10;
+            mag2 /= 10;
+            mag++;
+        }
+        for (i = -mag, j = -1; i < j; i++, j--)
+        {
+            p[i] ^= p[j];
+            p[j] ^= p[i];
+            p[i] ^= p[j];
+        }
+    }
+
+    return p - buf;
+}
+
 static ULONG format_guid( const GUID *ptr, unsigned char *buf )
 {
     static const char fmt[] = "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x";
@@ -1111,6 +1198,19 @@ static HRESULT text_to_utf8text( const WS_XML_TEXT *text, WS_XML_UTF8_TEXT **ret
         if (!(*ret = alloc_utf8_text( buf, len ))) return E_OUTOFMEMORY;
         return S_OK;
     }
+    case WS_XML_TEXT_TYPE_DOUBLE:
+    {
+        const WS_XML_DOUBLE_TEXT *double_text = (const WS_XML_DOUBLE_TEXT *)text;
+        unsigned char buf[24]; /* "-1.1111111111111111E-308" */
+        unsigned short fpword;
+        ULONG len;
+
+        if (!set_fp_rounding( &fpword )) return E_NOTIMPL;
+        len = format_double( &double_text->value, buf );
+        restore_fp_rounding( fpword );
+        if (!(*ret = alloc_utf8_text( buf, len ))) return E_OUTOFMEMORY;
+        return S_OK;
+    }
     case WS_XML_TEXT_TYPE_GUID:
     {
         const WS_XML_GUID_TEXT *id = (const WS_XML_GUID_TEXT *)text;
diff --git a/include/webservices.h b/include/webservices.h
index c9c2ade..e35e389 100644
--- a/include/webservices.h
+++ b/include/webservices.h
@@ -577,6 +577,11 @@ typedef struct _WS_XML_UINT64_TEXT {
     unsigned __int64 value;
 } WS_XML_UINT64_TEXT;
 
+typedef struct _WS_XML_DOUBLE_TEXT {
+    WS_XML_TEXT text;
+    double value;
+} WS_XML_DOUBLE_TEXT;
+
 typedef struct _WS_XML_GUID_TEXT {
     WS_XML_TEXT text;
     GUID value;




More information about the wine-cvs mailing list