webservices: Implement WsReadNode.

Signed-off-by: Hans Leidekker <hans@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Hans Leidekker 2015-10-09 10:19:31 +02:00 committed by Alexandre Julliard
parent 45ded33bc9
commit ef3e05ee5b
3 changed files with 348 additions and 4 deletions

View File

@ -273,6 +273,16 @@ static struct node *alloc_node( WS_XML_NODE_TYPE type )
return ret;
}
static void free_attribute( WS_XML_ATTRIBUTE *attr )
{
if (!attr) return;
heap_free( attr->prefix );
heap_free( attr->localName );
heap_free( attr->ns );
heap_free( attr->value );
heap_free( attr );
}
static void free_node( struct node *node )
{
if (!node) return;
@ -281,6 +291,10 @@ static void free_node( struct node *node )
case WS_XML_NODE_TYPE_ELEMENT:
{
WS_XML_ELEMENT_NODE *elem = (WS_XML_ELEMENT_NODE *)node;
ULONG i;
for (i = 0; i < elem->attributeCount; i++) free_attribute( elem->attributes[i] );
heap_free( elem->attributes );
heap_free( elem->prefix );
heap_free( elem->localName );
heap_free( elem->ns );
@ -705,12 +719,89 @@ static HRESULT read_xmldecl( struct reader *reader )
return S_OK;
}
static HRESULT append_attribute( WS_XML_ELEMENT_NODE *elem, WS_XML_ATTRIBUTE *attr )
{
if (elem->attributeCount)
{
WS_XML_ATTRIBUTE **tmp;
if (!(tmp = heap_realloc( elem->attributes, (elem->attributeCount + 1) * sizeof(attr) )))
return E_OUTOFMEMORY;
elem->attributes = tmp;
}
else if (!(elem->attributes = heap_alloc( sizeof(attr) ))) return E_OUTOFMEMORY;
elem->attributes[elem->attributeCount++] = attr;
return S_OK;
}
static HRESULT read_attribute( struct reader *reader, WS_XML_ATTRIBUTE **ret )
{
WS_XML_ATTRIBUTE *attr;
WS_XML_UTF8_TEXT *text;
unsigned int len = 0, ch, skip;
const char *start;
HRESULT hr = WS_E_INVALID_FORMAT;
if (!(attr = heap_alloc_zero( sizeof(*attr) ))) return E_OUTOFMEMORY;
start = read_current_ptr( reader );
for (;;)
{
if (!(ch = read_utf8_char( reader, &skip ))) goto error;
if (!read_isnamechar( ch )) break;
read_skip( reader, skip );
len += skip;
}
if (!len) goto error;
hr = E_OUTOFMEMORY;
if (!(attr->localName = alloc_xml_string( start, len ))) goto error;
if (!(attr->prefix = alloc_xml_string( NULL, 0 ))) goto error;
attr->prefix->bytes = NULL;
if (!(attr->ns = alloc_xml_string( NULL, 0 ))) goto error;
attr->ns->bytes = NULL;
hr = WS_E_INVALID_FORMAT;
read_skip_whitespace( reader );
if (read_cmp( reader, "=", 1 )) goto error;
read_skip( reader, 1 );
read_skip_whitespace( reader );
if (read_cmp( reader, "\"", 1 )) goto error;
read_skip( reader, 1 );
len = 0;
start = read_current_ptr( reader );
for (;;)
{
if (!(ch = read_utf8_char( reader, &skip ))) goto error;
if (ch == '"') break;
read_skip( reader, skip );
len += skip;
}
read_skip( reader, 1 );
if (!(text = alloc_utf8_text( start, len )))
{
free_attribute( attr );
return E_OUTOFMEMORY;
}
attr->value = (WS_XML_TEXT *)text;
*ret = attr;
return S_OK;
error:
free_attribute( attr );
return hr;
}
static HRESULT read_element( struct reader *reader )
{
unsigned int len = 0, ch, skip;
const char *start;
struct node *node;
WS_XML_ELEMENT_NODE *elem;
WS_XML_ATTRIBUTE *attr;
HRESULT hr = WS_E_INVALID_FORMAT;
if (read_end_of_data( reader ))
@ -742,10 +833,19 @@ static HRESULT read_element( struct reader *reader )
elem->prefix->bytes = NULL;
if (!(elem->ns = alloc_xml_string( NULL, 0 ))) goto error;
/* FIXME: parse attributes */
while (reader->read_pos < reader->read_size && reader->read_bufptr[reader->read_pos] != '>')
reader->read_pos++;
for (;;)
{
read_skip_whitespace( reader );
if (!read_cmp( reader, ">", 1 )) break;
if ((hr = read_attribute( reader, &attr )) != S_OK) goto error;
if ((hr = append_attribute( elem, attr )) != S_OK)
{
free_attribute( attr );
goto error;
}
}
read_skip_whitespace( reader );
if (read_cmp( reader, ">", 1 ))
{
hr = WS_E_INVALID_FORMAT;
@ -862,6 +962,29 @@ static HRESULT read_endelement( struct reader *reader )
return S_OK;
}
static HRESULT read_node( struct reader *reader )
{
HRESULT hr;
for (;;)
{
if (read_end_of_data( reader ))
{
reader->current = LIST_ENTRY( list_tail( &reader->nodes ), struct node, entry );
reader->state = READER_STATE_EOF;
return S_OK;
}
if (!read_cmp( reader, "<?", 2 ))
{
hr = read_xmldecl( reader );
if (FAILED( hr )) return hr;
}
else if (!read_cmp( reader, "</", 2 )) return read_endelement( reader );
else if (!read_cmp( reader, "<", 1 )) return read_startelement( reader );
else return read_text( reader );
}
}
/**************************************************************************
* WsReadEndElement [webservices.@]
*/
@ -876,6 +999,20 @@ HRESULT WINAPI WsReadEndElement( WS_XML_READER *handle, WS_ERROR *error )
return read_endelement( reader );
}
/**************************************************************************
* WsReadNode [webservices.@]
*/
HRESULT WINAPI WsReadNode( WS_XML_READER *handle, WS_ERROR *error )
{
struct reader *reader = (struct reader *)handle;
TRACE( "%p %p\n", handle, error );
if (error) FIXME( "ignoring error parameter\n" );
if (!reader) return E_INVALIDARG;
return read_node( reader );
}
/**************************************************************************
* WsReadStartElement [webservices.@]
*/

View File

@ -45,6 +45,13 @@ static const char data4[] =
"</o:services>\r\n"
"</o:OfficeConfig>\r\n";
static const char data5[] =
"</text>";
static const char data6[] =
"<?xml version=\"1.0\" encoding=\"utf-8\"?>"
"<text attr= \"value\" >test</text>";
static const char data8[] =
"<node1><node2>test</node2></node1>";
@ -694,6 +701,204 @@ static void test_WsReadStartElement(void)
WsFreeReader( reader );
}
static void test_WsReadEndElement(void)
{
HRESULT hr;
WS_XML_READER *reader;
const WS_XML_NODE *node;
hr = WsCreateReader( NULL, 0, &reader, NULL ) ;
ok( hr == S_OK, "got %08x\n", hr );
hr = set_input( reader, data2, sizeof(data2) - 1 );
ok( hr == S_OK, "got %08x\n", hr );
hr = WsFillReader( reader, sizeof(data2) - 1, NULL, NULL );
ok( hr == S_OK, "got %08x\n", hr );
hr = WsReadEndElement( reader, NULL );
ok( hr == WS_E_INVALID_FORMAT, "got %08x\n", hr );
hr = set_input( reader, data2, sizeof(data2) - 1 );
ok( hr == S_OK, "got %08x\n", hr );
hr = WsFillReader( reader, sizeof(data2) - 1, NULL, NULL );
ok( hr == S_OK, "got %08x\n", hr );
hr = WsReadNode( reader, NULL );
ok( hr == S_OK, "got %08x\n", hr );
hr = WsGetReaderNode( reader, &node, NULL );
ok( hr == S_OK, "got %08x\n", hr );
if (node) ok( node->nodeType == WS_XML_NODE_TYPE_ELEMENT, "got %u\n", node->nodeType );
hr = WsReadNode( reader, NULL );
ok( hr == S_OK, "got %08x\n", hr );
hr = WsGetReaderNode( reader, &node, NULL );
ok( hr == S_OK, "got %08x\n", hr );
if (node) ok( node->nodeType == WS_XML_NODE_TYPE_TEXT, "got %u\n", node->nodeType );
hr = WsReadNode( reader, NULL );
ok( hr == S_OK, "got %08x\n", hr );
hr = WsGetReaderNode( reader, &node, NULL );
ok( hr == S_OK, "got %08x\n", hr );
if (node) ok( node->nodeType == WS_XML_NODE_TYPE_END_ELEMENT, "got %u\n", node->nodeType );
hr = WsReadNode( reader, NULL );
ok( hr == S_OK, "got %08x\n", hr );
hr = WsGetReaderNode( reader, &node, NULL );
ok( hr == S_OK, "got %08x\n", hr );
if (node) ok( node->nodeType == WS_XML_NODE_TYPE_EOF, "got %u\n", node->nodeType );
hr = set_input( reader, data5, sizeof(data5) - 1 );
ok( hr == S_OK, "got %08x\n", hr );
hr = WsFillReader( reader, sizeof(data5) - 1, NULL, NULL );
ok( hr == S_OK, "got %08x\n", hr );
hr = WsReadEndElement( reader, NULL );
ok( hr == WS_E_INVALID_FORMAT, "got %08x\n", hr );
WsFreeReader( reader );
}
static void test_WsReadNode(void)
{
static const char str1[] = "<a>";
static const char str2[] = "< a>";
static const char str3[] = "<a >";
static const char str4[] = "<<a>>";
static const char str5[] = "<>";
static const char str6[] = "</a>";
static const char str7[] = " <a>";
static const char str8[] = "<?xml>";
static const char str9[] = "<?xml?>";
static const char str10[] = "<?xml ?>";
static const char str11[] = "<?xml version=\"1.0\"?>";
static const char str12[] = "<text>test</text>";
static const char str13[] = "<?xml version=\"1.0\"?><text>test</text>";
static const char str14[] = "";
HRESULT hr;
WS_XML_READER *reader;
const WS_XML_NODE *node;
unsigned int i;
int found;
static const struct
{
const char *text;
HRESULT hr;
WS_XML_NODE_TYPE type;
int todo;
}
tests[] =
{
{ str1, S_OK, WS_XML_NODE_TYPE_ELEMENT },
{ str2, WS_E_INVALID_FORMAT, 0 },
{ str3, S_OK, WS_XML_NODE_TYPE_ELEMENT },
{ str4, WS_E_INVALID_FORMAT, 0 },
{ str5, WS_E_INVALID_FORMAT, 0 },
{ str6, WS_E_INVALID_FORMAT, 0 },
{ str7, S_OK, WS_XML_NODE_TYPE_TEXT },
{ str8, WS_E_INVALID_FORMAT, 0 },
{ str9, WS_E_INVALID_FORMAT, 0 },
{ str10, WS_E_INVALID_FORMAT, 0, 1 },
{ str11, S_OK, WS_XML_NODE_TYPE_EOF },
{ str12, S_OK, WS_XML_NODE_TYPE_ELEMENT },
{ str13, S_OK, WS_XML_NODE_TYPE_ELEMENT },
{ str14, WS_E_INVALID_FORMAT, 0, 1 },
};
hr = WsCreateReader( NULL, 0, &reader, NULL ) ;
ok( hr == S_OK, "got %08x\n", hr );
for (i = 0; i < sizeof(tests)/sizeof(tests[0]); i++)
{
hr = set_input( reader, tests[i].text, strlen(tests[i].text) );
ok( hr == S_OK, "got %08x\n", hr );
hr = WsFillReader( reader, strlen(tests[i].text), NULL, NULL );
ok( hr == S_OK, "%u: got %08x\n", i, hr );
hr = WsReadNode( reader, NULL );
if (tests[i].todo)
todo_wine ok( hr == tests[i].hr, "%u: got %08x\n", i, hr );
else
ok( hr == tests[i].hr, "%u: got %08x\n", i, hr );
if (hr == S_OK)
{
node = NULL;
hr = WsGetReaderNode( reader, &node, NULL );
ok( hr == S_OK, "%u: got %08x\n", i, hr );
ok( node != NULL, "%u: node not set\n", i );
if (node)
{
if (tests[i].todo)
todo_wine
ok( node->nodeType == tests[i].type, "%u: got %u\n", i, node->nodeType );
else
ok( node->nodeType == tests[i].type, "%u: got %u\n", i, node->nodeType );
}
}
}
hr = set_input( reader, data6, sizeof(data6) - 1 );
ok( hr == S_OK, "got %08x\n", hr );
hr = WsFillReader( reader, sizeof(data6) - 1, NULL, NULL );
ok( hr == S_OK, "got %08x\n", hr );
found = -1;
hr = WsReadToStartElement( reader, NULL, NULL, &found, NULL );
ok( hr == S_OK, "got %08x\n", hr );
ok( found == TRUE, "got %d\n", found );
hr = WsGetReaderNode( reader, &node, NULL );
ok( hr == S_OK, "got %08x\n", hr );
if (node)
{
WS_XML_ELEMENT_NODE *elem = (WS_XML_ELEMENT_NODE *)node;
WS_XML_ATTRIBUTE *attr;
WS_XML_UTF8_TEXT *text;
ok( elem->node.nodeType == WS_XML_NODE_TYPE_ELEMENT, "got %u\n", elem->node.nodeType );
ok( elem->prefix != NULL, "prefix not set\n" );
ok( !elem->prefix->length, "got %u\n", elem->prefix->length );
ok( elem->prefix->bytes == NULL, "bytes set\n" );
ok( elem->localName != NULL, "localName not set\n" );
ok( elem->localName->length == 4, "got %u\n", elem->localName->length );
ok( !memcmp( elem->localName->bytes, "text", 4 ), "wrong data\n" );
ok( elem->ns != NULL, "ns not set\n" );
ok( !elem->ns->length, "got %u\n", elem->ns->length );
ok( elem->ns->bytes != NULL, "bytes not set\n" );
ok( elem->attributeCount == 1, "got %u\n", elem->attributeCount );
ok( elem->attributes != NULL, "attributes not set\n" );
ok( !elem->isEmpty, "isEmpty not zero\n" );
attr = elem->attributes[0];
ok( !attr->singleQuote, "got %u\n", attr->singleQuote );
ok( !attr->isXmlNs, "got %u\n", attr->isXmlNs );
ok( attr->prefix != NULL, "prefix not set\n" );
ok( !attr->prefix->length, "got %u\n", attr->prefix->length );
ok( attr->prefix->bytes == NULL, "bytes set\n" );
ok( attr->localName != NULL, "localName not set\n" );
ok( attr->localName->length == 4, "got %u\n", attr->localName->length );
ok( !memcmp( attr->localName->bytes, "attr", 4 ), "wrong data\n" );
ok( attr->ns != NULL, "ns not set\n" );
ok( !attr->ns->length, "got %u\n", attr->ns->length );
ok( attr->ns->bytes == NULL, "bytes set\n" );
ok( attr->value != NULL, "value not set\n" );
text = (WS_XML_UTF8_TEXT *)attr->value;
ok( attr->value->textType == WS_XML_TEXT_TYPE_UTF8, "got %u\n", attr->value->textType );
ok( text->value.length == 5, "got %u\n", text->value.length );
ok( !memcmp( text->value.bytes, "value", 5 ), "wrong data\n" );
}
WsFreeReader( reader );
}
START_TEST(reader)
{
test_WsCreateError();
@ -703,4 +908,6 @@ START_TEST(reader)
test_WsFillReader();
test_WsReadToStartElement();
test_WsReadStartElement();
test_WsReadEndElement();
test_WsReadNode();
}

View File

@ -116,7 +116,7 @@
@ stub WsReadMessageEnd
@ stub WsReadMessageStart
@ stub WsReadMetadata
@ stub WsReadNode
@ stdcall WsReadNode(ptr ptr)
@ stub WsReadQualifiedName
@ stub WsReadStartAttribute
@ stdcall WsReadStartElement(ptr ptr)