diff --git a/dlls/webservices/reader.c b/dlls/webservices/reader.c index 6d1d68f4d2b..0028334d517 100644 --- a/dlls/webservices/reader.c +++ b/dlls/webservices/reader.c @@ -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; diff --git a/dlls/webservices/tests/reader.c b/dlls/webservices/tests/reader.c index 072a46ea033..0eaf350c13b 100644 --- a/dlls/webservices/tests/reader.c +++ b/dlls/webservices/tests/reader.c @@ -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[] = + { + {"0.0", S_OK, 0}, + {"-0.0", S_OK, 0x80000000}, + {"+0.0", S_OK, 0}, + {"-", S_OK, 0}, + {"+", S_OK, 0}, + {".0", S_OK, 0}, + {"0.", S_OK, 0}, + {"0", S_OK, 0}, + {" 0 ", S_OK, 0}, + {"", WS_E_INVALID_FORMAT, 0}, + {"0,1", WS_E_INVALID_FORMAT, 0}, + {"1.1.", WS_E_INVALID_FORMAT, 0}, + {"1", S_OK, 0x3f800000}, + {"1.0000001", S_OK, 0x3f800001}, + {"1.0000002", S_OK, 0x3f800002}, + {"10000000000000000000", S_OK, 0x5f0ac723}, + {"100000000000000000000", S_OK, 0x60ad78ec}, + {"2", S_OK, 0x40000000}, + {"-2", S_OK, 0xc0000000}, + {"nofloat", WS_E_INVALID_FORMAT, 0}, + {"INF", S_OK, 0x7f800000}, + {"-INF", S_OK, 0xff800000}, + {"+INF", WS_E_INVALID_FORMAT, 0}, + {"Infinity", WS_E_INVALID_FORMAT, 0}, + {"-Infinity", WS_E_INVALID_FORMAT, 0}, + {"inf", WS_E_INVALID_FORMAT, 0}, + {"NaN", S_OK, 0xffc00000}, + {"-NaN", WS_E_INVALID_FORMAT, 0}, + {"NAN", WS_E_INVALID_FORMAT, 0}, + {"0.3", S_OK, 0x3e99999a}, + {"0.33", S_OK, 0x3ea8f5c3}, + {"0.333", S_OK, 0x3eaa7efa}, + {"0.3333", S_OK, 0x3eaaa64c}, + {"0.33333", S_OK, 0x3eaaaa3b}, + {"0.333333", S_OK, 0x3eaaaa9f}, + {"0.3333333", S_OK, 0x3eaaaaaa}, + {"0.33333333", S_OK, 0x3eaaaaab}, + {"0.333333333", S_OK, 0x3eaaaaab}, + {"0.1e10", S_OK, 0x4e6e6b28}, + {"1e", WS_E_INVALID_FORMAT, 0}, + {"1e0", S_OK, 0x3f800000}, + {"1e+1", S_OK, 0x41200000}, + {"1e-1", S_OK, 0x3dcccccd}, + {"e10", WS_E_INVALID_FORMAT, 0}, + {"1e10.", WS_E_INVALID_FORMAT, 0}, + {"1E10", S_OK, 0x501502f9}, + {"1e10", S_OK, 0x501502f9}, + {"1e-10", S_OK, 0x2edbe6ff}, + {"3.4028235e38", S_OK, 0x7f7fffff}, + {"3.4028236e38", S_OK, 0x7f800000}, + {"1.1754942e-38", S_OK, 0x007fffff}, + {"1.1754943e-38", 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(); } diff --git a/dlls/webservices/webservices_private.h b/dlls/webservices/webservices_private.h index b88a50c0f82..5557d321b23 100644 --- a/dlls/webservices/webservices_private.h +++ b/dlls/webservices/webservices_private.h @@ -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; diff --git a/include/webservices.h b/include/webservices.h index 2af333a588d..1f823ddc273 100644 --- a/include/webservices.h +++ b/include/webservices.h @@ -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;