[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