Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-winehq
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
wine
wine-winehq
Commits
524fa657
Commit
524fa657
authored
May 18, 2016
by
Hans Leidekker
Committed by
Alexandre Julliard
May 18, 2016
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
webservices: Add support for reading double values.
Signed-off-by:
Hans Leidekker
<
hans@codeweavers.com
>
Signed-off-by:
Alexandre Julliard
<
julliard@winehq.org
>
parent
6e0366fd
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
306 additions
and
0 deletions
+306
-0
reader.c
dlls/webservices/reader.c
+210
-0
reader.c
dlls/webservices/tests/reader.c
+96
-0
No files found.
dlls/webservices/reader.c
View file @
524fa657
...
...
@@ -1937,6 +1937,160 @@ static HRESULT str_to_uint64( const unsigned char *str, ULONG len, UINT64 max, U
return
S_OK
;
}
#if defined(__i386__) || defined(__x86_64__)
#define RC_DOWN 0x100;
static
BOOL
set_fp_rounding
(
unsigned
short
*
save
)
{
#ifdef __GNUC__
unsigned
short
fpword
;
__asm__
__volatile__
(
"fstcw %0"
:
"=m"
(
fpword
)
);
*
save
=
fpword
;
fpword
|=
RC_DOWN
;
__asm__
__volatile__
(
"fldcw %0"
:
:
"m"
(
fpword
)
);
return
TRUE
;
#else
FIXME
(
"not implemented
\n
"
);
return
FALSE
;
#endif
}
static
void
restore_fp_rounding
(
unsigned
short
fpword
)
{
#ifdef __GNUC__
__asm__
__volatile__
(
"fldcw %0"
:
:
"m"
(
fpword
)
);
#else
FIXME
(
"not implemented
\n
"
);
#endif
}
#else
static
BOOL
set_fp_rounding
(
unsigned
short
*
save
)
{
FIXME
(
"not implemented
\n
"
);
return
FALSE
;
}
static
void
restore_fp_rounding
(
unsigned
short
fpword
)
{
FIXME
(
"not implemented
\n
"
);
}
#endif
static
HRESULT
str_to_double
(
const
unsigned
char
*
str
,
ULONG
len
,
double
*
ret
)
{
static
const
unsigned
__int64
nan
=
0xfff8000000000000
;
static
const
unsigned
__int64
inf
=
0x7ff0000000000000
;
static
const
unsigned
__int64
inf_min
=
0xfff0000000000000
;
HRESULT
hr
=
WS_E_INVALID_FORMAT
;
const
unsigned
char
*
p
=
str
,
*
q
;
int
sign
=
1
,
exp_sign
=
1
,
exp
=
0
,
exp_tmp
=
0
,
neg_exp
,
i
,
nb_digits
,
have_digits
;
unsigned
__int64
val
=
0
,
tmp
;
long
double
exp_val
=
1
.
0
,
exp_mul
=
10
.
0
;
unsigned
short
fpword
;
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
,
"NaN"
,
3
))
{
*
(
unsigned
__int64
*
)
ret
=
nan
;
return
S_OK
;
}
else
if
(
len
==
3
&&
!
memcmp
(
p
,
"INF"
,
3
))
{
*
(
unsigned
__int64
*
)
ret
=
inf
;
return
S_OK
;
}
else
if
(
len
==
4
&&
!
memcmp
(
p
,
"-INF"
,
4
))
{
*
(
unsigned
__int64
*
)
ret
=
inf_min
;
return
S_OK
;
}
*
ret
=
0
.
0
;
if
(
*
p
==
'-'
)
{
sign
=
-
1
;
p
++
;
len
--
;
}
else
if
(
*
p
==
'+'
)
{
p
++
;
len
--
;
};
if
(
!
len
)
return
S_OK
;
if
(
!
set_fp_rounding
(
&
fpword
))
return
E_NOTIMPL
;
q
=
p
;
while
(
len
&&
isdigit
(
*
q
))
{
q
++
;
len
--
;
}
have_digits
=
nb_digits
=
q
-
p
;
for
(
i
=
0
;
i
<
nb_digits
;
i
++
)
{
tmp
=
val
*
10
+
p
[
i
]
-
'0'
;
if
(
val
>
MAX_UINT64
/
10
||
tmp
<
val
)
{
for
(;
i
<
nb_digits
;
i
++
)
exp
++
;
break
;
}
val
=
tmp
;
}
if
(
len
)
{
if
(
*
q
==
'.'
)
{
p
=
++
q
;
len
--
;
while
(
len
&&
isdigit
(
*
q
))
{
q
++
;
len
--
;
};
have_digits
|=
nb_digits
=
q
-
p
;
for
(
i
=
0
;
i
<
nb_digits
;
i
++
)
{
tmp
=
val
*
10
+
p
[
i
]
-
'0'
;
if
(
val
>
MAX_UINT64
/
10
||
tmp
<
val
)
break
;
val
=
tmp
;
exp
--
;
}
}
if
(
len
>
1
&&
tolower
(
*
q
)
==
'e'
)
{
if
(
!
have_digits
)
goto
done
;
p
=
++
q
;
len
--
;
if
(
*
p
==
'-'
)
{
exp_sign
=
-
1
;
p
++
;
len
--
;
}
else
if
(
*
p
==
'+'
)
{
p
++
;
len
--
;
};
q
=
p
;
while
(
len
&&
isdigit
(
*
q
))
{
q
++
;
len
--
;
};
nb_digits
=
q
-
p
;
if
(
!
nb_digits
||
len
)
goto
done
;
for
(
i
=
0
;
i
<
nb_digits
;
i
++
)
{
if
(
exp_tmp
>
MAX_INT32
/
10
||
(
exp_tmp
=
exp_tmp
*
10
+
p
[
i
]
-
'0'
)
<
0
)
exp_tmp
=
MAX_INT32
;
}
exp_tmp
*=
exp_sign
;
if
(
exp
<
0
&&
exp_tmp
<
0
&&
exp
+
exp_tmp
>=
0
)
exp
=
MIN_INT32
;
else
if
(
exp
>
0
&&
exp_tmp
>
0
&&
exp
+
exp_tmp
<
0
)
exp
=
MAX_INT32
;
else
exp
+=
exp_tmp
;
}
}
if
(
!
have_digits
||
len
)
goto
done
;
if
((
neg_exp
=
exp
<
0
))
exp
=
-
exp
;
for
(;
exp
;
exp
>>=
1
)
{
if
(
exp
&
1
)
exp_val
*=
exp_mul
;
exp_mul
*=
exp_mul
;
}
*
ret
=
sign
*
(
neg_exp
?
val
/
exp_val
:
val
*
exp_val
);
hr
=
S_OK
;
done:
restore_fp_rounding
(
fpword
);
return
hr
;
}
#define TICKS_PER_SEC 10000000
#define TICKS_PER_MIN (60 * (ULONGLONG)TICKS_PER_SEC)
#define TICKS_PER_HOUR (3600 * (ULONGLONG)TICKS_PER_SEC)
...
...
@@ -2711,6 +2865,53 @@ static HRESULT read_type_uint64( struct reader *reader, WS_TYPE_MAPPING mapping,
return
S_OK
;
}
static
HRESULT
read_type_double
(
struct
reader
*
reader
,
WS_TYPE_MAPPING
mapping
,
const
WS_XML_STRING
*
localname
,
const
WS_XML_STRING
*
ns
,
const
WS_DOUBLE_DESCRIPTION
*
desc
,
WS_READ_OPTION
option
,
WS_HEAP
*
heap
,
void
*
ret
,
ULONG
size
)
{
WS_XML_UTF8_TEXT
*
utf8
;
HRESULT
hr
;
double
val
=
0
.
0
;
BOOL
found
;
if
(
desc
)
FIXME
(
"ignoring description
\n
"
);
if
((
hr
=
read_get_text
(
reader
,
mapping
,
localname
,
ns
,
&
utf8
,
&
found
))
!=
S_OK
)
return
hr
;
if
(
found
&&
(
hr
=
str_to_double
(
utf8
->
value
.
bytes
,
utf8
->
value
.
length
,
&
val
))
!=
S_OK
)
return
hr
;
switch
(
option
)
{
case
WS_READ_REQUIRED_VALUE
:
if
(
!
found
)
return
WS_E_INVALID_FORMAT
;
if
(
size
!=
sizeof
(
double
))
return
E_INVALIDARG
;
*
(
double
*
)
ret
=
val
;
break
;
case
WS_READ_REQUIRED_POINTER
:
if
(
!
found
)
return
WS_E_INVALID_FORMAT
;
/* fall through */
case
WS_READ_OPTIONAL_POINTER
:
{
double
*
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
;
}
*
(
double
**
)
ret
=
heap_val
;
break
;
}
default:
FIXME
(
"read option %u not supported
\n
"
,
option
);
return
E_NOTIMPL
;
}
return
S_OK
;
}
static
HRESULT
read_type_wsz
(
struct
reader
*
reader
,
WS_TYPE_MAPPING
mapping
,
const
WS_XML_STRING
*
localname
,
const
WS_XML_STRING
*
ns
,
const
WS_WSZ_DESCRIPTION
*
desc
,
WS_READ_OPTION
option
,
...
...
@@ -2958,6 +3159,9 @@ static ULONG get_type_size( WS_TYPE type, const WS_STRUCT_DESCRIPTION *desc )
case
WS_UINT64_TYPE
:
return
sizeof
(
INT64
);
case
WS_DOUBLE_TYPE
:
return
sizeof
(
double
);
case
WS_DATETIME_TYPE
:
return
sizeof
(
WS_DATETIME
);
...
...
@@ -3091,6 +3295,7 @@ static WS_READ_OPTION get_field_read_option( WS_TYPE type )
case
WS_UINT16_TYPE
:
case
WS_UINT32_TYPE
:
case
WS_UINT64_TYPE
:
case
WS_DOUBLE_TYPE
:
case
WS_ENUM_TYPE
:
case
WS_DATETIME_TYPE
:
return
WS_READ_REQUIRED_VALUE
;
...
...
@@ -3322,6 +3527,11 @@ static HRESULT read_type( struct reader *reader, WS_TYPE_MAPPING mapping, WS_TYP
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
;
break
;
case
WS_WSZ_TYPE
:
if
((
hr
=
read_type_wsz
(
reader
,
mapping
,
localname
,
ns
,
desc
,
option
,
heap
,
value
,
size
))
!=
S_OK
)
return
hr
;
...
...
dlls/webservices/tests/reader.c
View file @
524fa657
...
...
@@ -3176,6 +3176,101 @@ static void test_WsFileTimeToDateTime(void)
ok
(
hr
==
WS_E_NUMERIC_OVERFLOW
,
"got %08x
\n
"
,
hr
);
}
static
void
test_double
(
void
)
{
static
const
struct
{
const
char
*
str
;
HRESULT
hr
;
ULONGLONG
val
;
}
tests
[]
=
{
{
"<t>0.0</t>"
,
S_OK
,
0
},
{
"<t>-0.0</t>"
,
S_OK
,
0x8000000000000000
},
{
"<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
,
0x3ff0000000000000
},
{
"<t>1.0000000000000002</t>"
,
S_OK
,
0x3ff0000000000001
},
{
"<t>1.0000000000000004</t>"
,
S_OK
,
0x3ff0000000000002
},
{
"<t>10000000000000000000</t>"
,
S_OK
,
0x43e158e460913d00
},
{
"<t>100000000000000000000</t>"
,
S_OK
,
0x4415af1d78b58c40
},
{
"<t>2</t>"
,
S_OK
,
0x4000000000000000
},
{
"<t>-2</t>"
,
S_OK
,
0xc000000000000000
},
{
"<t>nodouble</t>"
,
WS_E_INVALID_FORMAT
,
0
},
{
"<t>INF</t>"
,
S_OK
,
0x7ff0000000000000
},
{
"<t>-INF</t>"
,
S_OK
,
0xfff0000000000000
},
{
"<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
,
0xfff8000000000000
},
{
"<t>-NaN</t>"
,
WS_E_INVALID_FORMAT
,
0
},
{
"<t>NAN</t>"
,
WS_E_INVALID_FORMAT
,
0
},
{
"<t>0.3</t>"
,
S_OK
,
0x3fd3333333333333
},
{
"<t>0.33</t>"
,
S_OK
,
0x3fd51eb851eb851f
},
{
"<t>0.333</t>"
,
S_OK
,
0x3fd54fdf3b645a1d
},
{
"<t>0.3333</t>"
,
S_OK
,
0x3fd554c985f06f69
},
{
"<t>0.33333</t>"
,
S_OK
,
0x3fd555475a31a4be
},
{
"<t>0.333333</t>"
,
S_OK
,
0x3fd55553ef6b5d46
},
{
"<t>0.3333333</t>"
,
S_OK
,
0x3fd55555318abc87
},
{
"<t>0.33333333</t>"
,
S_OK
,
0x3fd5555551c112da
},
{
"<t>0.333333333</t>"
,
S_OK
,
0x3fd5555554f9b516
},
{
"<t>0.3333333333</t>"
,
S_OK
,
0x3fd55555554c2bb5
},
{
"<t>0.33333333333</t>"
,
S_OK
,
0x3fd5555555546ac5
},
{
"<t>0.3333333333333</t>"
,
S_OK
,
0x3fd55555555552fd
},
{
"<t>0.33333333333333</t>"
,
S_OK
,
0x3fd5555555555519
},
{
"<t>0.333333333333333</t>"
,
S_OK
,
0x3fd555555555554f
},
{
"<t>0.3333333333333333</t>"
,
S_OK
,
0x3fd5555555555555
},
{
"<t>0.33333333333333333</t>"
,
S_OK
,
0x3fd5555555555555
},
{
"<t>0.1e10</t>"
,
S_OK
,
0x41cdcd6500000000
},
{
"<t>1e</t>"
,
WS_E_INVALID_FORMAT
,
0
},
{
"<t>1e0</t>"
,
S_OK
,
0x3ff0000000000000
},
{
"<t>1e+1</t>"
,
S_OK
,
0x4024000000000000
},
{
"<t>1e-1</t>"
,
S_OK
,
0x3fb999999999999a
},
{
"<t>e10</t>"
,
WS_E_INVALID_FORMAT
,
0
},
{
"<t>1e10.</t>"
,
WS_E_INVALID_FORMAT
,
0
},
{
"<t>1E10</t>"
,
S_OK
,
0x4202a05f20000000
},
{
"<t>1e10</t>"
,
S_OK
,
0x4202a05f20000000
},
{
"<t>1e-10</t>"
,
S_OK
,
0x3ddb7cdfd9d7bdbb
},
{
"<t>1.7976931348623158e308</t>"
,
S_OK
,
0x7fefffffffffffff
},
{
"<t>1.7976931348623159e308</t>"
,
S_OK
,
0x7ff0000000000000
},
{
"<t>4.94065645841247e-324</t>"
,
S_OK
,
0x1
},
};
HRESULT
hr
;
WS_XML_READER
*
reader
;
WS_HEAP
*
heap
;
ULONGLONG
val
;
ULONG
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_DOUBLE_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 %x%08x
\n
"
,
i
,
(
ULONG
)(
val
>>
32
),
(
ULONG
)
val
);
}
WsFreeReader
(
reader
);
WsFreeHeap
(
heap
);
}
START_TEST
(
reader
)
{
test_WsCreateError
();
...
...
@@ -3204,4 +3299,5 @@ START_TEST(reader)
test_datetime
();
test_WsDateTimeToFileTime
();
test_WsFileTimeToDateTime
();
test_double
();
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment