[4/5] webservices: Implement WsReadNode.
Hans Leidekker
hans at codeweavers.com
Fri Oct 9 03:19:31 CDT 2015
Signed-off-by: Hans Leidekker <hans at codeweavers.com>
---
dlls/webservices/reader.c | 143 +++++++++++++++++++++++++-
dlls/webservices/tests/reader.c | 207 ++++++++++++++++++++++++++++++++++++++
dlls/webservices/webservices.spec | 2 +-
3 files changed, 348 insertions(+), 4 deletions(-)
diff --git a/dlls/webservices/reader.c b/dlls/webservices/reader.c
index e48a8f2..5da43d6 100644
--- a/dlls/webservices/reader.c
+++ b/dlls/webservices/reader.c
@@ -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.@]
*/
@@ -877,6 +1000,20 @@ HRESULT WINAPI WsReadEndElement( WS_XML_READER *handle, WS_ERROR *error )
}
/**************************************************************************
+ * 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.@]
*/
HRESULT WINAPI WsReadStartElement( WS_XML_READER *handle, WS_ERROR *error )
diff --git a/dlls/webservices/tests/reader.c b/dlls/webservices/tests/reader.c
index 6baee49..f5c6650 100644
--- a/dlls/webservices/tests/reader.c
+++ b/dlls/webservices/tests/reader.c
@@ -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();
}
diff --git a/dlls/webservices/webservices.spec b/dlls/webservices/webservices.spec
index 4a587e7..a91f5c7 100644
--- a/dlls/webservices/webservices.spec
+++ b/dlls/webservices/webservices.spec
@@ -116,7 +116,7 @@
@ stub WsReadMessageEnd
@ stub WsReadMessageStart
@ stub WsReadMetadata
-@ stub WsReadNode
+@ stdcall WsReadNode(ptr ptr)
@ stub WsReadQualifiedName
@ stub WsReadStartAttribute
@ stdcall WsReadStartElement(ptr ptr)
--
2.6.1
More information about the wine-patches
mailing list