webservices: Add support for reading float values.
Signed-off-by: Hans Leidekker <hans@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
fb22f6c416
commit
82306e84f3
|
@ -851,6 +851,16 @@ WS_XML_UINT64_TEXT *alloc_uint64_text( UINT64 value )
|
|||
return ret;
|
||||
}
|
||||
|
||||
WS_XML_FLOAT_TEXT *alloc_float_text( float value )
|
||||
{
|
||||
WS_XML_FLOAT_TEXT *ret;
|
||||
|
||||
if (!(ret = heap_alloc( sizeof(*ret) ))) return NULL;
|
||||
ret->text.textType = WS_XML_TEXT_TYPE_FLOAT;
|
||||
ret->value = value;
|
||||
return ret;
|
||||
}
|
||||
|
||||
WS_XML_DOUBLE_TEXT *alloc_double_text( double value )
|
||||
{
|
||||
WS_XML_DOUBLE_TEXT *ret;
|
||||
|
@ -1465,6 +1475,16 @@ static HRESULT read_attribute_value_bin( struct reader *reader, WS_XML_ATTRIBUTE
|
|||
attr->value = &text_int64->text;
|
||||
return S_OK;
|
||||
}
|
||||
case RECORD_FLOAT_TEXT:
|
||||
{
|
||||
WS_XML_FLOAT_TEXT *text_float;
|
||||
float val_float;
|
||||
|
||||
if ((hr = read_bytes( reader, (unsigned char *)&val_float, sizeof(val_float) )) != S_OK) return hr;
|
||||
if (!(text_float = alloc_float_text( val_float ))) return E_OUTOFMEMORY;
|
||||
attr->value = &text_float->text;
|
||||
return S_OK;
|
||||
}
|
||||
case RECORD_DOUBLE_TEXT:
|
||||
{
|
||||
WS_XML_DOUBLE_TEXT *text_double;
|
||||
|
@ -2145,6 +2165,23 @@ static struct node *alloc_int64_text_node( INT64 value )
|
|||
return node;
|
||||
}
|
||||
|
||||
static struct node *alloc_float_text_node( float value )
|
||||
{
|
||||
struct node *node;
|
||||
WS_XML_FLOAT_TEXT *text_float;
|
||||
WS_XML_TEXT_NODE *text;
|
||||
|
||||
if (!(node = alloc_node( WS_XML_NODE_TYPE_TEXT ))) return NULL;
|
||||
if (!(text_float = alloc_float_text( value )))
|
||||
{
|
||||
heap_free( node );
|
||||
return NULL;
|
||||
}
|
||||
text = (WS_XML_TEXT_NODE *)node;
|
||||
text->text = &text_float->text;
|
||||
return node;
|
||||
}
|
||||
|
||||
static struct node *alloc_double_text_node( double value )
|
||||
{
|
||||
struct node *node;
|
||||
|
@ -2384,6 +2421,14 @@ static HRESULT read_text_bin( struct reader *reader )
|
|||
if (!(node = alloc_int64_text_node( val_int64 ))) return E_OUTOFMEMORY;
|
||||
break;
|
||||
}
|
||||
case RECORD_FLOAT_TEXT:
|
||||
case RECORD_FLOAT_TEXT_WITH_ENDELEMENT:
|
||||
{
|
||||
float val_float;
|
||||
if ((hr = read_bytes( reader, (unsigned char *)&val_float, sizeof(val_float) )) != S_OK) return hr;
|
||||
if (!(node = alloc_float_text_node( val_float ))) return E_OUTOFMEMORY;
|
||||
break;
|
||||
}
|
||||
case RECORD_DOUBLE_TEXT:
|
||||
case RECORD_DOUBLE_TEXT_WITH_ENDELEMENT:
|
||||
{
|
||||
|
@ -3608,12 +3653,12 @@ static HRESULT str_to_double( const unsigned char *str, ULONG len, double *ret )
|
|||
*(unsigned __int64 *)ret = nan;
|
||||
return S_OK;
|
||||
}
|
||||
else if (len == 3 && !memcmp( p, "INF", 3 ))
|
||||
if (len == 3 && !memcmp( p, "INF", 3 ))
|
||||
{
|
||||
*(unsigned __int64 *)ret = inf;
|
||||
return S_OK;
|
||||
}
|
||||
else if (len == 4 && !memcmp( p, "-INF", 4 ))
|
||||
if (len == 4 && !memcmp( p, "-INF", 4 ))
|
||||
{
|
||||
*(unsigned __int64 *)ret = inf_min;
|
||||
return S_OK;
|
||||
|
@ -3703,6 +3748,34 @@ done:
|
|||
return hr;
|
||||
}
|
||||
|
||||
static HRESULT str_to_float( const unsigned char *str, ULONG len, float *ret )
|
||||
{
|
||||
static const unsigned int inf = 0x7f800000;
|
||||
static const unsigned int inf_min = 0xff800000;
|
||||
const unsigned char *p = str;
|
||||
double val;
|
||||
HRESULT hr;
|
||||
|
||||
while (len && read_isspace( *p )) { p++; len--; }
|
||||
while (len && read_isspace( p[len - 1] )) { len--; }
|
||||
if (!len) return WS_E_INVALID_FORMAT;
|
||||
|
||||
if (len == 3 && !memcmp( p, "INF", 3 ))
|
||||
{
|
||||
*(unsigned int *)ret = inf;
|
||||
return S_OK;
|
||||
}
|
||||
if (len == 4 && !memcmp( p, "-INF", 4 ))
|
||||
{
|
||||
*(unsigned int *)ret = inf_min;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
if ((hr = str_to_double( p, len, &val )) != S_OK) return hr;
|
||||
*ret = val;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static HRESULT str_to_guid( const unsigned char *str, ULONG len, GUID *ret )
|
||||
{
|
||||
static const unsigned char hex[] =
|
||||
|
@ -5008,6 +5081,84 @@ static HRESULT read_type_uint64( struct reader *reader, WS_TYPE_MAPPING mapping,
|
|||
return S_OK;
|
||||
}
|
||||
|
||||
static HRESULT text_to_float( const WS_XML_TEXT *text, float *val )
|
||||
{
|
||||
HRESULT hr;
|
||||
|
||||
switch (text->textType)
|
||||
{
|
||||
case WS_XML_TEXT_TYPE_UTF8:
|
||||
{
|
||||
const WS_XML_UTF8_TEXT *text_utf8 = (const WS_XML_UTF8_TEXT *)text;
|
||||
hr = str_to_float( text_utf8->value.bytes, text_utf8->value.length, val );
|
||||
break;
|
||||
}
|
||||
case WS_XML_TEXT_TYPE_FLOAT:
|
||||
{
|
||||
const WS_XML_FLOAT_TEXT *text_float = (const WS_XML_FLOAT_TEXT *)text;
|
||||
*val = text_float->value;
|
||||
hr = S_OK;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
FIXME( "unhandled text type %u\n", text->textType );
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
static HRESULT read_type_float( struct reader *reader, WS_TYPE_MAPPING mapping,
|
||||
const WS_XML_STRING *localname, const WS_XML_STRING *ns,
|
||||
const WS_FLOAT_DESCRIPTION *desc, WS_READ_OPTION option,
|
||||
WS_HEAP *heap, void *ret, ULONG size )
|
||||
{
|
||||
const WS_XML_TEXT *text;
|
||||
HRESULT hr;
|
||||
float val = 0.0;
|
||||
BOOL found;
|
||||
|
||||
if (desc) FIXME( "ignoring description\n" );
|
||||
|
||||
if ((hr = get_text( reader, mapping, localname, ns, &text, &found )) != S_OK) return hr;
|
||||
if (found && (hr = text_to_float( text, &val )) != S_OK) return hr;
|
||||
|
||||
switch (option)
|
||||
{
|
||||
case WS_READ_REQUIRED_VALUE:
|
||||
if (!found) return WS_E_INVALID_FORMAT;
|
||||
/* fall through */
|
||||
|
||||
case WS_READ_NILLABLE_VALUE:
|
||||
if (size != sizeof(val)) return E_INVALIDARG;
|
||||
*(float *)ret = val;
|
||||
break;
|
||||
|
||||
case WS_READ_REQUIRED_POINTER:
|
||||
if (!found) return WS_E_INVALID_FORMAT;
|
||||
/* fall through */
|
||||
|
||||
case WS_READ_OPTIONAL_POINTER:
|
||||
case WS_READ_NILLABLE_POINTER:
|
||||
{
|
||||
float *heap_val = NULL;
|
||||
if (size != sizeof(heap_val)) return E_INVALIDARG;
|
||||
if (found)
|
||||
{
|
||||
if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
|
||||
*heap_val = val;
|
||||
}
|
||||
*(float **)ret = heap_val;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
FIXME( "read option %u not supported\n", option );
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static HRESULT text_to_double( const WS_XML_TEXT *text, double *val )
|
||||
{
|
||||
HRESULT hr;
|
||||
|
@ -5843,6 +5994,9 @@ ULONG get_type_size( WS_TYPE type, const void *desc )
|
|||
case WS_UINT64_TYPE:
|
||||
return sizeof(INT64);
|
||||
|
||||
case WS_FLOAT_TYPE:
|
||||
return sizeof(float);
|
||||
|
||||
case WS_DOUBLE_TYPE:
|
||||
return sizeof(double);
|
||||
|
||||
|
@ -5909,6 +6063,7 @@ static WS_READ_OPTION get_field_read_option( WS_TYPE type, ULONG options )
|
|||
case WS_UINT16_TYPE:
|
||||
case WS_UINT32_TYPE:
|
||||
case WS_UINT64_TYPE:
|
||||
case WS_FLOAT_TYPE:
|
||||
case WS_DOUBLE_TYPE:
|
||||
case WS_DATETIME_TYPE:
|
||||
case WS_GUID_TYPE:
|
||||
|
@ -6365,6 +6520,11 @@ static HRESULT read_type( struct reader *reader, WS_TYPE_MAPPING mapping, WS_TYP
|
|||
return hr;
|
||||
break;
|
||||
|
||||
case WS_FLOAT_TYPE:
|
||||
if ((hr = read_type_float( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
|
||||
return hr;
|
||||
break;
|
||||
|
||||
case WS_DOUBLE_TYPE:
|
||||
if ((hr = read_type_double( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
|
||||
return hr;
|
||||
|
|
|
@ -6174,6 +6174,94 @@ static void test_union_type(void)
|
|||
WsFreeHeap( heap );
|
||||
}
|
||||
|
||||
static void test_float(void)
|
||||
{
|
||||
static const struct
|
||||
{
|
||||
const char *str;
|
||||
HRESULT hr;
|
||||
ULONG val;
|
||||
}
|
||||
tests[] =
|
||||
{
|
||||
{"<t>0.0</t>", S_OK, 0},
|
||||
{"<t>-0.0</t>", S_OK, 0x80000000},
|
||||
{"<t>+0.0</t>", S_OK, 0},
|
||||
{"<t>-</t>", S_OK, 0},
|
||||
{"<t>+</t>", S_OK, 0},
|
||||
{"<t>.0</t>", S_OK, 0},
|
||||
{"<t>0.</t>", S_OK, 0},
|
||||
{"<t>0</t>", S_OK, 0},
|
||||
{"<t> 0 </t>", S_OK, 0},
|
||||
{"<t></t>", WS_E_INVALID_FORMAT, 0},
|
||||
{"<t>0,1</t>", WS_E_INVALID_FORMAT, 0},
|
||||
{"<t>1.1.</t>", WS_E_INVALID_FORMAT, 0},
|
||||
{"<t>1</t>", S_OK, 0x3f800000},
|
||||
{"<t>1.0000001</t>", S_OK, 0x3f800001},
|
||||
{"<t>1.0000002</t>", S_OK, 0x3f800002},
|
||||
{"<t>10000000000000000000</t>", S_OK, 0x5f0ac723},
|
||||
{"<t>100000000000000000000</t>", S_OK, 0x60ad78ec},
|
||||
{"<t>2</t>", S_OK, 0x40000000},
|
||||
{"<t>-2</t>", S_OK, 0xc0000000},
|
||||
{"<t>nofloat</t>", WS_E_INVALID_FORMAT, 0},
|
||||
{"<t>INF</t>", S_OK, 0x7f800000},
|
||||
{"<t>-INF</t>", S_OK, 0xff800000},
|
||||
{"<t>+INF</t>", WS_E_INVALID_FORMAT, 0},
|
||||
{"<t>Infinity</t>", WS_E_INVALID_FORMAT, 0},
|
||||
{"<t>-Infinity</t>", WS_E_INVALID_FORMAT, 0},
|
||||
{"<t>inf</t>", WS_E_INVALID_FORMAT, 0},
|
||||
{"<t>NaN</t>", S_OK, 0xffc00000},
|
||||
{"<t>-NaN</t>", WS_E_INVALID_FORMAT, 0},
|
||||
{"<t>NAN</t>", WS_E_INVALID_FORMAT, 0},
|
||||
{"<t>0.3</t>", S_OK, 0x3e99999a},
|
||||
{"<t>0.33</t>", S_OK, 0x3ea8f5c3},
|
||||
{"<t>0.333</t>", S_OK, 0x3eaa7efa},
|
||||
{"<t>0.3333</t>", S_OK, 0x3eaaa64c},
|
||||
{"<t>0.33333</t>", S_OK, 0x3eaaaa3b},
|
||||
{"<t>0.333333</t>", S_OK, 0x3eaaaa9f},
|
||||
{"<t>0.3333333</t>", S_OK, 0x3eaaaaaa},
|
||||
{"<t>0.33333333</t>", S_OK, 0x3eaaaaab},
|
||||
{"<t>0.333333333</t>", S_OK, 0x3eaaaaab},
|
||||
{"<t>0.1e10</t>", S_OK, 0x4e6e6b28},
|
||||
{"<t>1e</t>", WS_E_INVALID_FORMAT, 0},
|
||||
{"<t>1e0</t>", S_OK, 0x3f800000},
|
||||
{"<t>1e+1</t>", S_OK, 0x41200000},
|
||||
{"<t>1e-1</t>", S_OK, 0x3dcccccd},
|
||||
{"<t>e10</t>", WS_E_INVALID_FORMAT, 0},
|
||||
{"<t>1e10.</t>", WS_E_INVALID_FORMAT, 0},
|
||||
{"<t>1E10</t>", S_OK, 0x501502f9},
|
||||
{"<t>1e10</t>", S_OK, 0x501502f9},
|
||||
{"<t>1e-10</t>", S_OK, 0x2edbe6ff},
|
||||
{"<t>3.4028235e38</t>", S_OK, 0x7f7fffff},
|
||||
{"<t>3.4028236e38</t>", S_OK, 0x7f800000},
|
||||
{"<t>1.1754942e-38</t>", S_OK, 0x007fffff},
|
||||
{"<t>1.1754943e-38</t>", S_OK, 0x00800000},
|
||||
};
|
||||
HRESULT hr;
|
||||
WS_XML_READER *reader;
|
||||
WS_HEAP *heap;
|
||||
ULONG val, i;
|
||||
|
||||
hr = WsCreateHeap( 1 << 16, 0, NULL, 0, &heap, NULL );
|
||||
ok( hr == S_OK, "got %08x\n", hr );
|
||||
|
||||
hr = WsCreateReader( NULL, 0, &reader, NULL );
|
||||
ok( hr == S_OK, "got %08x\n", hr );
|
||||
|
||||
for (i = 0; i < sizeof(tests)/sizeof(tests[0]); i++)
|
||||
{
|
||||
val = 0;
|
||||
prepare_type_test( reader, tests[i].str, strlen(tests[i].str) );
|
||||
hr = WsReadType( reader, WS_ELEMENT_CONTENT_TYPE_MAPPING, WS_FLOAT_TYPE, NULL,
|
||||
WS_READ_REQUIRED_VALUE, heap, &val, sizeof(val), NULL );
|
||||
ok( hr == tests[i].hr, "%u: got %08x\n", i, hr );
|
||||
if (hr == tests[i].hr) ok( val == tests[i].val, "%u: got %08x\n", i, val );
|
||||
}
|
||||
|
||||
WsFreeReader( reader );
|
||||
WsFreeHeap( heap );
|
||||
}
|
||||
|
||||
START_TEST(reader)
|
||||
{
|
||||
test_WsCreateError();
|
||||
|
@ -6220,4 +6308,5 @@ START_TEST(reader)
|
|||
test_dictionary();
|
||||
test_WsReadXmlBuffer();
|
||||
test_union_type();
|
||||
test_float();
|
||||
}
|
||||
|
|
|
@ -66,6 +66,7 @@ WS_XML_BOOL_TEXT *alloc_bool_text( BOOL ) DECLSPEC_HIDDEN;
|
|||
WS_XML_INT32_TEXT *alloc_int32_text( INT32 ) DECLSPEC_HIDDEN;
|
||||
WS_XML_INT64_TEXT *alloc_int64_text( INT64 ) DECLSPEC_HIDDEN;
|
||||
WS_XML_UINT64_TEXT *alloc_uint64_text( UINT64 ) DECLSPEC_HIDDEN;
|
||||
WS_XML_FLOAT_TEXT *alloc_float_text( float ) DECLSPEC_HIDDEN;
|
||||
WS_XML_DOUBLE_TEXT *alloc_double_text( double ) DECLSPEC_HIDDEN;
|
||||
WS_XML_GUID_TEXT *alloc_guid_text( const GUID * ) DECLSPEC_HIDDEN;
|
||||
WS_XML_UNIQUE_ID_TEXT *alloc_unique_id_text( const GUID * ) DECLSPEC_HIDDEN;
|
||||
|
|
|
@ -56,6 +56,7 @@ typedef struct _WS_OPERATION_DESCRIPTION WS_OPERATION_DESCRIPTION;
|
|||
typedef struct _WS_PARAMETER_DESCRIPTION WS_PARAMETER_DESCRIPTION;
|
||||
typedef struct _WS_OPERATION_CONTEXT WS_OPERATION_CONTEXT;
|
||||
typedef struct _WS_CALL_PROPERTY WS_CALL_PROPERTY;
|
||||
typedef struct _WS_FLOAT_DESCRIPTION WS_FLOAT_DESCRIPTION;
|
||||
typedef struct _WS_DOUBLE_DESCRIPTION WS_DOUBLE_DESCRIPTION;
|
||||
typedef struct _WS_DATETIME WS_DATETIME;
|
||||
typedef struct _WS_XML_DATETIME_TEXT WS_XML_DATETIME_TEXT;
|
||||
|
@ -442,6 +443,11 @@ struct _WS_ENUM_DESCRIPTION {
|
|||
ULONG *nameIndices;
|
||||
};
|
||||
|
||||
struct _WS_FLOAT_DESCRIPTION {
|
||||
float minValue;
|
||||
float maxValue;
|
||||
};
|
||||
|
||||
struct _WS_DOUBLE_DESCRIPTION {
|
||||
double DECLSPEC_ALIGN(8) minValue;
|
||||
double DECLSPEC_ALIGN(8) maxValue;
|
||||
|
@ -654,6 +660,11 @@ typedef struct _WS_XML_UINT64_TEXT {
|
|||
unsigned __int64 DECLSPEC_ALIGN(8) value;
|
||||
} WS_XML_UINT64_TEXT;
|
||||
|
||||
typedef struct _WS_XML_FLOAT_TEXT {
|
||||
WS_XML_TEXT text;
|
||||
float value;
|
||||
} WS_XML_FLOAT_TEXT;
|
||||
|
||||
typedef struct _WS_XML_DOUBLE_TEXT {
|
||||
WS_XML_TEXT text;
|
||||
double DECLSPEC_ALIGN(8) value;
|
||||
|
|
Loading…
Reference in New Issue