[6/8] webservices: Implement WsMoveWriter.

Hans Leidekker hans at codeweavers.com
Tue Jun 21 07:04:46 CDT 2016


Signed-off-by: Hans Leidekker <hans at codeweavers.com>
---
 dlls/webservices/reader.c              | 151 +++++++++++++++++++--------------
 dlls/webservices/tests/writer.c        |  71 ++++++++++++++++
 dlls/webservices/webservices.spec      |   2 +-
 dlls/webservices/webservices_private.h |  13 +++
 dlls/webservices/writer.c              |  87 +++++++++++++++++++
 5 files changed, 258 insertions(+), 66 deletions(-)

diff --git a/dlls/webservices/reader.c b/dlls/webservices/reader.c
index 8f2d8fb..b8dfed4 100644
--- a/dlls/webservices/reader.c
+++ b/dlls/webservices/reader.c
@@ -1549,24 +1549,24 @@ HRESULT WINAPI WsReadToStartElement( WS_XML_READER *handle, const WS_XML_STRING
     return read_to_startelement( reader, found );
 }
 
-static BOOL move_to_root_element( struct reader *reader )
+BOOL move_to_root_element( struct node *root, struct node **current )
 {
     struct list *ptr;
     struct node *node;
 
-    if (!(ptr = list_head( &reader->root->children ))) return FALSE;
+    if (!(ptr = list_head( &root->children ))) return FALSE;
     node = LIST_ENTRY( ptr, struct node, entry );
     if (node_type( node ) == WS_XML_NODE_TYPE_ELEMENT)
     {
-        reader->current = node;
+        *current = node;
         return TRUE;
     }
-    while ((ptr = list_next( &reader->root->children, &node->entry )))
+    while ((ptr = list_next( &root->children, &node->entry )))
     {
         struct node *next = LIST_ENTRY( ptr, struct node, entry );
         if (node_type( next ) == WS_XML_NODE_TYPE_ELEMENT)
         {
-            reader->current = next;
+            *current = next;
             return TRUE;
         }
         node = next;
@@ -1574,17 +1574,18 @@ static BOOL move_to_root_element( struct reader *reader )
     return FALSE;
 }
 
-static BOOL move_to_next_element( struct reader *reader )
+BOOL move_to_next_element( struct node **current )
 {
     struct list *ptr;
-    struct node *node = reader->current;
+    struct node *node = *current, *parent = (*current)->parent;
 
-    while ((ptr = list_next( &node->parent->children, &node->entry )))
+    if (!parent) return FALSE;
+    while ((ptr = list_next( &parent->children, &node->entry )))
     {
         struct node *next = LIST_ENTRY( ptr, struct node, entry );
         if (node_type( next ) == WS_XML_NODE_TYPE_ELEMENT)
         {
-            reader->current = next;
+            *current = next;
             return TRUE;
         }
         node = next;
@@ -1592,17 +1593,18 @@ static BOOL move_to_next_element( struct reader *reader )
     return FALSE;
 }
 
-static BOOL move_to_prev_element( struct reader *reader )
+BOOL move_to_prev_element( struct node **current )
 {
     struct list *ptr;
-    struct node *node = reader->current;
+    struct node *node = *current, *parent = (*current)->parent;
 
-    while ((ptr = list_prev( &node->parent->children, &node->entry )))
+    if (!parent) return FALSE;
+    while ((ptr = list_prev( &parent->children, &node->entry )))
     {
         struct node *prev = LIST_ENTRY( ptr, struct node, entry );
         if (node_type( prev ) == WS_XML_NODE_TYPE_ELEMENT)
         {
-            reader->current = prev;
+            *current = prev;
             return TRUE;
         }
         node = prev;
@@ -1610,35 +1612,35 @@ static BOOL move_to_prev_element( struct reader *reader )
     return FALSE;
 }
 
-static BOOL move_to_child_element( struct reader *reader )
+BOOL move_to_child_element( struct node **current )
 {
     struct list *ptr;
-    struct node *node;
+    struct node *child, *node = *current;
 
-    if (!(ptr = list_head( &reader->current->children ))) return FALSE;
-    node = LIST_ENTRY( ptr, struct node, entry );
-    if (node_type( node ) == WS_XML_NODE_TYPE_ELEMENT)
+    if (!(ptr = list_head( &node->children ))) return FALSE;
+    child = LIST_ENTRY( ptr, struct node, entry );
+    if (node_type( child ) == WS_XML_NODE_TYPE_ELEMENT)
     {
-        reader->current = node;
+        *current = child;
         return TRUE;
     }
-    while ((ptr = list_next( &reader->current->children, &node->entry )))
+    while ((ptr = list_next( &node->children, &child->entry )))
     {
         struct node *next = LIST_ENTRY( ptr, struct node, entry );
         if (node_type( next ) == WS_XML_NODE_TYPE_ELEMENT)
         {
-            reader->current = next;
+            *current = next;
             return TRUE;
         }
-        node = next;
+        child = next;
     }
     return FALSE;
 }
 
-static BOOL move_to_end_element( struct reader *reader )
+BOOL move_to_end_element( struct node **current )
 {
     struct list *ptr;
-    struct node *node = reader->current;
+    struct node *node = *current;
 
     if (node_type( node ) != WS_XML_NODE_TYPE_ELEMENT) return FALSE;
 
@@ -1647,81 +1649,105 @@ static BOOL move_to_end_element( struct reader *reader )
         struct node *tail = LIST_ENTRY( ptr, struct node, entry );
         if (node_type( tail ) == WS_XML_NODE_TYPE_END_ELEMENT)
         {
-            reader->current = tail;
+            *current = tail;
             return TRUE;
         }
     }
     return FALSE;
 }
 
-static BOOL move_to_parent_element( struct reader *reader )
+BOOL move_to_parent_element( struct node **current )
 {
-    struct node *parent = reader->current->parent;
+    struct node *parent = (*current)->parent;
 
     if (parent && (node_type( parent ) == WS_XML_NODE_TYPE_ELEMENT ||
                    node_type( parent ) == WS_XML_NODE_TYPE_BOF))
     {
-        reader->current = parent;
+        *current = parent;
         return TRUE;
     }
     return FALSE;
 }
 
-static BOOL move_to_first_node( struct reader *reader )
+BOOL move_to_first_node( struct node **current )
 {
     struct list *ptr;
-    if ((ptr = list_head( &reader->current->parent->children )))
+    struct node *node = *current;
+
+    if ((ptr = list_head( &node->parent->children )))
     {
-        reader->current = LIST_ENTRY( ptr, struct node, entry );
+        *current = LIST_ENTRY( ptr, struct node, entry );
         return TRUE;
     }
     return FALSE;
 }
 
-static BOOL move_to_next_node( struct reader *reader )
+BOOL move_to_next_node( struct node **current )
 {
     struct list *ptr;
-    if ((ptr = list_next( &reader->current->parent->children, &reader->current->entry )))
+    struct node *node = *current;
+
+    if ((ptr = list_next( &node->parent->children, &node->entry )))
     {
-        reader->current = LIST_ENTRY( ptr, struct node, entry );
+        *current = LIST_ENTRY( ptr, struct node, entry );
         return TRUE;
     }
     return FALSE;
 }
 
-static BOOL move_to_prev_node( struct reader *reader )
+BOOL move_to_prev_node( struct node **current )
 {
     struct list *ptr;
-    if ((ptr = list_prev( &reader->current->parent->children, &reader->current->entry )))
+    struct node *node = *current;
+
+    if ((ptr = list_prev( &node->parent->children, &node->entry )))
     {
-        reader->current = LIST_ENTRY( ptr, struct node, entry );
+        *current = LIST_ENTRY( ptr, struct node, entry );
         return TRUE;
     }
     return FALSE;
 }
 
-static BOOL move_to_child_node( struct reader *reader )
+BOOL move_to_bof( struct node *root, struct node **current )
+{
+    *current = root;
+    return TRUE;
+}
+
+BOOL move_to_eof( struct node *root, struct node **current )
 {
     struct list *ptr;
-    if ((ptr = list_head( &reader->current->children )))
+    if ((ptr = list_tail( &root->children )))
     {
-        reader->current = LIST_ENTRY( ptr, struct node, entry );
+        *current = LIST_ENTRY( ptr, struct node, entry );
         return TRUE;
     }
     return FALSE;
 }
 
-static BOOL move_to_parent_node( struct reader *reader )
+BOOL move_to_child_node( struct node **current )
 {
-    struct node *parent = reader->current->parent;
+    struct list *ptr;
+    struct node *node = *current;
+
+    if ((ptr = list_head( &node->children )))
+    {
+        *current = LIST_ENTRY( ptr, struct node, entry );
+        return TRUE;
+    }
+    return FALSE;
+}
+
+static BOOL move_to_parent_node( struct node **current )
+{
+    struct node *parent = (*current)->parent;
     if (!parent) return FALSE;
-    reader->current = parent;
+    *current = parent;
     return TRUE;
 }
 
 static HRESULT read_move_to( struct reader *reader, WS_MOVE_TO move, BOOL *found )
 {
-    struct list *ptr;
     BOOL success = FALSE;
     HRESULT hr = S_OK;
 
@@ -1733,56 +1759,51 @@ static HRESULT read_move_to( struct reader *reader, WS_MOVE_TO move, BOOL *found
     switch (move)
     {
     case WS_MOVE_TO_ROOT_ELEMENT:
-        success = move_to_root_element( reader );
+        success = move_to_root_element( reader->root, &reader->current );
         break;
 
     case WS_MOVE_TO_NEXT_ELEMENT:
-        success = move_to_next_element( reader );
+        success = move_to_next_element( &reader->current );
         break;
 
     case WS_MOVE_TO_PREVIOUS_ELEMENT:
-        success = move_to_prev_element( reader );
+        success = move_to_prev_element( &reader->current );
         break;
 
     case WS_MOVE_TO_CHILD_ELEMENT:
-        success = move_to_child_element( reader );
+        success = move_to_child_element( &reader->current );
         break;
 
     case WS_MOVE_TO_END_ELEMENT:
-        success = move_to_end_element( reader );
+        success = move_to_end_element( &reader->current );
         break;
 
     case WS_MOVE_TO_PARENT_ELEMENT:
-        success = move_to_parent_element( reader );
+        success = move_to_parent_element( &reader->current );
         break;
 
     case WS_MOVE_TO_FIRST_NODE:
-        success = move_to_first_node( reader );
+        success = move_to_first_node( &reader->current );
         break;
 
     case WS_MOVE_TO_NEXT_NODE:
-        success = move_to_next_node( reader );
+        success = move_to_next_node( &reader->current );
         break;
 
     case WS_MOVE_TO_PREVIOUS_NODE:
-        success = move_to_prev_node( reader );
+        success = move_to_prev_node( &reader->current );
         break;
 
     case WS_MOVE_TO_CHILD_NODE:
-        success = move_to_child_node( reader );
+        success = move_to_child_node( &reader->current );
         break;
 
     case WS_MOVE_TO_BOF:
-        reader->current = reader->root;
-        success = TRUE;
+        success = move_to_bof( reader->root, &reader->current );
         break;
 
     case WS_MOVE_TO_EOF:
-        if ((ptr = list_tail( &reader->root->children )))
-        {
-            reader->current = LIST_ENTRY( ptr, struct node, entry );
-            success = TRUE;
-        }
+        success = move_to_eof( reader->root, &reader->current );
         break;
 
     default:
@@ -3186,10 +3207,10 @@ static BOOL is_empty_text_node( const struct node *node )
 static HRESULT read_next_node( struct reader *reader )
 {
     if (reader->current == reader->last) return read_node( reader );
-    if (move_to_child_node( reader )) return S_OK;
-    if (move_to_next_node( reader )) return S_OK;
-    if (!move_to_parent_node( reader )) return WS_E_INVALID_FORMAT;
-    if (move_to_next_node( reader )) return S_OK;
+    if (move_to_child_node( &reader->current )) return S_OK;
+    if (move_to_next_node( &reader->current )) return S_OK;
+    if (!move_to_parent_node( &reader->current )) return WS_E_INVALID_FORMAT;
+    if (move_to_next_node( &reader->current )) return S_OK;
     return WS_E_INVALID_FORMAT;
 }
 
diff --git a/dlls/webservices/tests/writer.c b/dlls/webservices/tests/writer.c
index 4e22887..b223544 100644
--- a/dlls/webservices/tests/writer.c
+++ b/dlls/webservices/tests/writer.c
@@ -1415,6 +1415,76 @@ static void test_complex_struct_type(void)
     WsFreeHeap( heap );
 }
 
+static void test_WsMoveWriter(void)
+{
+    WS_XML_STRING localname = {1, (BYTE *)"a"}, localname2 = {1, (BYTE *)"b"}, ns = {0, NULL};
+    WS_HEAP *heap;
+    WS_XML_WRITER *writer;
+    WS_XML_BUFFER *buffer;
+    HRESULT hr;
+
+    hr = WsMoveWriter( NULL, WS_MOVE_TO_EOF, NULL, NULL );
+    ok( hr == E_INVALIDARG, "got %08x\n", hr );
+
+    hr = WsCreateHeap( 1 << 16, 0, NULL, 0, &heap, NULL );
+    ok( hr == S_OK, "got %08x\n", hr );
+
+    hr = WsCreateWriter( NULL, 0, &writer, NULL ) ;
+    ok( hr == S_OK, "got %08x\n", hr );
+
+    hr = set_output( writer );
+    ok( hr == S_OK, "got %08x\n", hr );
+
+    /* writer must be set to an XML buffer */
+    hr = WsMoveWriter( writer, WS_MOVE_TO_EOF, NULL, NULL );
+    todo_wine ok( hr == WS_E_INVALID_OPERATION, "got %08x\n", hr );
+
+    hr = WsCreateXmlBuffer( heap, NULL, 0, &buffer, NULL );
+    ok( hr == S_OK, "got %08x\n", hr );
+
+    hr = WsSetOutputToBuffer( writer, buffer, NULL, 0, NULL );
+    ok( hr == S_OK, "got %08x\n", hr );
+
+    hr = WsMoveWriter( writer, WS_MOVE_TO_EOF, NULL, NULL );
+    ok( hr == S_OK, "got %08x\n", hr );
+
+    /* <a><b/></a> */
+    hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
+    ok( hr == S_OK, "got %08x\n", hr );
+
+    hr = WsWriteStartElement( writer, NULL, &localname2, &ns, NULL );
+    ok( hr == S_OK, "got %08x\n", hr );
+
+    hr = WsWriteEndElement( writer, NULL );
+    ok( hr == S_OK, "got %08x\n", hr );
+
+    hr = WsWriteEndElement( writer, NULL );
+    ok( hr == S_OK, "got %08x\n", hr );
+
+    hr = WsMoveWriter( writer, WS_MOVE_TO_EOF, NULL, NULL );
+    ok( hr == S_OK, "got %08x\n", hr );
+
+    hr = WsMoveWriter( writer, WS_MOVE_TO_ROOT_ELEMENT, NULL, NULL );
+    ok( hr == S_OK, "got %08x\n", hr );
+
+    hr = WsMoveWriter( writer, WS_MOVE_TO_CHILD_ELEMENT, NULL, NULL );
+    ok( hr == S_OK, "got %08x\n", hr );
+
+    hr = WsMoveWriter( writer, WS_MOVE_TO_END_ELEMENT, NULL, NULL );
+    ok( hr == S_OK, "got %08x\n", hr );
+
+    hr = WsMoveWriter( writer, WS_MOVE_TO_PARENT_ELEMENT, NULL, NULL );
+    ok( hr == S_OK, "got %08x\n", hr );
+
+    hr = WsMoveWriter( writer, WS_MOVE_TO_END_ELEMENT, NULL, NULL );
+    ok( hr == S_OK, "got %08x\n", hr );
+
+    hr = WsMoveWriter( writer, WS_MOVE_TO_BOF, NULL, NULL );
+    ok( hr == E_INVALIDARG, "got %08x\n", hr );
+
+    WsFreeWriter( writer );
+    WsFreeHeap( heap );
+}
 
 START_TEST(writer)
 {
@@ -1434,4 +1504,5 @@ START_TEST(writer)
     test_WsWriteXmlnsAttribute();
     test_WsGetPrefixFromNamespace();
     test_complex_struct_type();
+    test_WsMoveWriter();
 }
diff --git a/dlls/webservices/webservices.spec b/dlls/webservices/webservices.spec
index 0093fc0..5754c61 100644
--- a/dlls/webservices/webservices.spec
+++ b/dlls/webservices/webservices.spec
@@ -94,7 +94,7 @@
 @ stub WsMarkHeaderAsUnderstood
 @ stub WsMatchPolicyAlternative
 @ stdcall WsMoveReader(ptr long ptr ptr)
-@ stub WsMoveWriter
+@ stdcall WsMoveWriter(ptr long ptr ptr)
 @ stdcall WsOpenChannel(ptr ptr ptr ptr)
 @ stub WsOpenListener
 @ stub WsOpenServiceHost
diff --git a/dlls/webservices/webservices_private.h b/dlls/webservices/webservices_private.h
index fc888ee..74ee5a4 100644
--- a/dlls/webservices/webservices_private.h
+++ b/dlls/webservices/webservices_private.h
@@ -52,6 +52,19 @@ static inline WS_XML_NODE_TYPE node_type( const struct node *node )
     return node->hdr.node.nodeType;
 }
 
+BOOL move_to_root_element( struct node *, struct node ** ) DECLSPEC_HIDDEN;
+BOOL move_to_next_element( struct node ** ) DECLSPEC_HIDDEN;
+BOOL move_to_prev_element( struct node ** ) DECLSPEC_HIDDEN;
+BOOL move_to_child_element( struct node ** ) DECLSPEC_HIDDEN;
+BOOL move_to_end_element( struct node ** ) DECLSPEC_HIDDEN;
+BOOL move_to_parent_element( struct node ** ) DECLSPEC_HIDDEN;
+BOOL move_to_first_node( struct node ** ) DECLSPEC_HIDDEN;
+BOOL move_to_next_node( struct node ** ) DECLSPEC_HIDDEN;
+BOOL move_to_prev_node( struct node ** ) DECLSPEC_HIDDEN;
+BOOL move_to_bof( struct node *, struct node ** ) DECLSPEC_HIDDEN;
+BOOL move_to_eof( struct node *, struct node ** ) DECLSPEC_HIDDEN;
+BOOL move_to_child_node( struct node ** ) DECLSPEC_HIDDEN;
+
 struct prop_desc
 {
     ULONG size;
diff --git a/dlls/webservices/writer.c b/dlls/webservices/writer.c
index bf4c61b..583e7fa 100644
--- a/dlls/webservices/writer.c
+++ b/dlls/webservices/writer.c
@@ -1714,3 +1714,90 @@ HRESULT WINAPI WsWriteXmlnsAttribute( WS_XML_WRITER *handle, const WS_XML_STRING
     if (namespace_in_scope( &writer->current->hdr, prefix, ns )) return S_OK;
     return write_add_namespace_attribute( writer, prefix, ns, single );
 }
+
+static HRESULT write_move_to( struct writer *writer, WS_MOVE_TO move, BOOL *found )
+{
+    BOOL success = FALSE;
+    struct node *node = writer->current;
+
+    switch (move)
+    {
+    case WS_MOVE_TO_ROOT_ELEMENT:
+        success = move_to_root_element( writer->root, &node );
+        break;
+
+    case WS_MOVE_TO_NEXT_ELEMENT:
+        success = move_to_next_element( &node );
+        break;
+
+    case WS_MOVE_TO_PREVIOUS_ELEMENT:
+        success = move_to_prev_element( &node );
+        break;
+
+    case WS_MOVE_TO_CHILD_ELEMENT:
+        success = move_to_child_element( &node );
+        break;
+
+    case WS_MOVE_TO_END_ELEMENT:
+        success = move_to_end_element( &node );
+        break;
+
+    case WS_MOVE_TO_PARENT_ELEMENT:
+        success = move_to_parent_element( &node );
+        break;
+
+    case WS_MOVE_TO_FIRST_NODE:
+        success = move_to_first_node( &node );
+        break;
+
+    case WS_MOVE_TO_NEXT_NODE:
+        success = move_to_next_node( &node );
+        break;
+
+    case WS_MOVE_TO_PREVIOUS_NODE:
+        success = move_to_prev_node( &node );
+        break;
+
+    case WS_MOVE_TO_CHILD_NODE:
+        success = move_to_child_node( &node );
+        break;
+
+    case WS_MOVE_TO_BOF:
+        success = move_to_bof( writer->root, &node );
+        break;
+
+    case WS_MOVE_TO_EOF:
+        success = move_to_eof( writer->root, &node );
+        break;
+
+    default:
+        FIXME( "unhandled move %u\n", move );
+        return E_NOTIMPL;
+    }
+
+    if (success && node == writer->root) return E_INVALIDARG;
+    writer->current = node;
+
+    if (found)
+    {
+        *found = success;
+        return S_OK;
+    }
+    return success ? S_OK : WS_E_INVALID_FORMAT;
+}
+
+/**************************************************************************
+ *          WsMoveWriter		[webservices.@]
+ */
+HRESULT WINAPI WsMoveWriter( WS_XML_WRITER *handle, WS_MOVE_TO move, BOOL *found, WS_ERROR *error )
+{
+    struct writer *writer = (struct writer *)handle;
+
+    TRACE( "%p %u %p %p\n", handle, move, found, error );
+    if (error) FIXME( "ignoring error parameter\n" );
+
+    if (!writer) return E_INVALIDARG;
+    if (!writer->output_type) return WS_E_INVALID_OPERATION;
+
+    return write_move_to( writer, move, found );
+}
-- 
2.8.1




More information about the wine-patches mailing list