[01/10] webservices: Add support for writing double values.
Hans Leidekker
hans at codeweavers.com
Thu Jul 7 02:31:51 CDT 2016
Signed-off-by: Hans Leidekker <hans at codeweavers.com>
---
dlls/webservices/reader.c | 8 +--
dlls/webservices/tests/writer.c | 113 +++++++++++++++++++++++++++++++++
dlls/webservices/webservices_private.h | 2 +
dlls/webservices/writer.c | 100 +++++++++++++++++++++++++++++
4 files changed, 219 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;
--
2.1.4
More information about the wine-patches
mailing list