webservices: Add support for writing double values.
Signed-off-by: Hans Leidekker <hans@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
10925fa451
commit
df4046a370
|
@ -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" );
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue