webservices: Implement WsMoveWriter.

Signed-off-by: Hans Leidekker <hans@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Hans Leidekker 2016-06-21 14:04:46 +02:00 committed by Alexandre Julliard
parent f5c8f69725
commit 768197795d
5 changed files with 258 additions and 66 deletions

View File

@ -1549,24 +1549,24 @@ HRESULT WINAPI WsReadToStartElement( WS_XML_READER *handle, const WS_XML_STRING
return read_to_startelement( reader, found ); 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 list *ptr;
struct node *node; 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 ); node = LIST_ENTRY( ptr, struct node, entry );
if (node_type( node ) == WS_XML_NODE_TYPE_ELEMENT) if (node_type( node ) == WS_XML_NODE_TYPE_ELEMENT)
{ {
reader->current = node; *current = node;
return TRUE; 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 ); struct node *next = LIST_ENTRY( ptr, struct node, entry );
if (node_type( next ) == WS_XML_NODE_TYPE_ELEMENT) if (node_type( next ) == WS_XML_NODE_TYPE_ELEMENT)
{ {
reader->current = next; *current = next;
return TRUE; return TRUE;
} }
node = next; node = next;
@ -1574,17 +1574,18 @@ static BOOL move_to_root_element( struct reader *reader )
return FALSE; return FALSE;
} }
static BOOL move_to_next_element( struct reader *reader ) BOOL move_to_next_element( struct node **current )
{ {
struct list *ptr; 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 ); struct node *next = LIST_ENTRY( ptr, struct node, entry );
if (node_type( next ) == WS_XML_NODE_TYPE_ELEMENT) if (node_type( next ) == WS_XML_NODE_TYPE_ELEMENT)
{ {
reader->current = next; *current = next;
return TRUE; return TRUE;
} }
node = next; node = next;
@ -1592,17 +1593,18 @@ static BOOL move_to_next_element( struct reader *reader )
return FALSE; return FALSE;
} }
static BOOL move_to_prev_element( struct reader *reader ) BOOL move_to_prev_element( struct node **current )
{ {
struct list *ptr; 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 ); struct node *prev = LIST_ENTRY( ptr, struct node, entry );
if (node_type( prev ) == WS_XML_NODE_TYPE_ELEMENT) if (node_type( prev ) == WS_XML_NODE_TYPE_ELEMENT)
{ {
reader->current = prev; *current = prev;
return TRUE; return TRUE;
} }
node = prev; node = prev;
@ -1610,35 +1612,35 @@ static BOOL move_to_prev_element( struct reader *reader )
return FALSE; return FALSE;
} }
static BOOL move_to_child_element( struct reader *reader ) BOOL move_to_child_element( struct node **current )
{ {
struct list *ptr; struct list *ptr;
struct node *node; struct node *child, *node = *current;
if (!(ptr = list_head( &reader->current->children ))) return FALSE; if (!(ptr = list_head( &node->children ))) return FALSE;
node = LIST_ENTRY( ptr, struct node, entry ); child = LIST_ENTRY( ptr, struct node, entry );
if (node_type( node ) == WS_XML_NODE_TYPE_ELEMENT) if (node_type( child ) == WS_XML_NODE_TYPE_ELEMENT)
{ {
reader->current = node; *current = child;
return TRUE; 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 ); struct node *next = LIST_ENTRY( ptr, struct node, entry );
if (node_type( next ) == WS_XML_NODE_TYPE_ELEMENT) if (node_type( next ) == WS_XML_NODE_TYPE_ELEMENT)
{ {
reader->current = next; *current = next;
return TRUE; return TRUE;
} }
node = next; child = next;
} }
return FALSE; return FALSE;
} }
static BOOL move_to_end_element( struct reader *reader ) BOOL move_to_end_element( struct node **current )
{ {
struct list *ptr; struct list *ptr;
struct node *node = reader->current; struct node *node = *current;
if (node_type( node ) != WS_XML_NODE_TYPE_ELEMENT) return FALSE; 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 ); struct node *tail = LIST_ENTRY( ptr, struct node, entry );
if (node_type( tail ) == WS_XML_NODE_TYPE_END_ELEMENT) if (node_type( tail ) == WS_XML_NODE_TYPE_END_ELEMENT)
{ {
reader->current = tail; *current = tail;
return TRUE; return TRUE;
} }
} }
return FALSE; 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 || if (parent && (node_type( parent ) == WS_XML_NODE_TYPE_ELEMENT ||
node_type( parent ) == WS_XML_NODE_TYPE_BOF)) node_type( parent ) == WS_XML_NODE_TYPE_BOF))
{ {
reader->current = parent; *current = parent;
return TRUE; return TRUE;
} }
return FALSE; return FALSE;
} }
static BOOL move_to_first_node( struct reader *reader ) BOOL move_to_first_node( struct node **current )
{ {
struct list *ptr; 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 TRUE;
} }
return FALSE; return FALSE;
} }
static BOOL move_to_next_node( struct reader *reader ) BOOL move_to_next_node( struct node **current )
{ {
struct list *ptr; 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 TRUE;
} }
return FALSE; return FALSE;
} }
static BOOL move_to_prev_node( struct reader *reader ) BOOL move_to_prev_node( struct node **current )
{ {
struct list *ptr; 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 TRUE;
} }
return FALSE; 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; 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 TRUE;
} }
return FALSE; 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; if (!parent) return FALSE;
reader->current = parent; *current = parent;
return TRUE; return TRUE;
} }
static HRESULT read_move_to( struct reader *reader, WS_MOVE_TO move, BOOL *found ) static HRESULT read_move_to( struct reader *reader, WS_MOVE_TO move, BOOL *found )
{ {
struct list *ptr;
BOOL success = FALSE; BOOL success = FALSE;
HRESULT hr = S_OK; HRESULT hr = S_OK;
@ -1733,56 +1759,51 @@ static HRESULT read_move_to( struct reader *reader, WS_MOVE_TO move, BOOL *found
switch (move) switch (move)
{ {
case WS_MOVE_TO_ROOT_ELEMENT: case WS_MOVE_TO_ROOT_ELEMENT:
success = move_to_root_element( reader ); success = move_to_root_element( reader->root, &reader->current );
break; break;
case WS_MOVE_TO_NEXT_ELEMENT: case WS_MOVE_TO_NEXT_ELEMENT:
success = move_to_next_element( reader ); success = move_to_next_element( &reader->current );
break; break;
case WS_MOVE_TO_PREVIOUS_ELEMENT: case WS_MOVE_TO_PREVIOUS_ELEMENT:
success = move_to_prev_element( reader ); success = move_to_prev_element( &reader->current );
break; break;
case WS_MOVE_TO_CHILD_ELEMENT: case WS_MOVE_TO_CHILD_ELEMENT:
success = move_to_child_element( reader ); success = move_to_child_element( &reader->current );
break; break;
case WS_MOVE_TO_END_ELEMENT: case WS_MOVE_TO_END_ELEMENT:
success = move_to_end_element( reader ); success = move_to_end_element( &reader->current );
break; break;
case WS_MOVE_TO_PARENT_ELEMENT: case WS_MOVE_TO_PARENT_ELEMENT:
success = move_to_parent_element( reader ); success = move_to_parent_element( &reader->current );
break; break;
case WS_MOVE_TO_FIRST_NODE: case WS_MOVE_TO_FIRST_NODE:
success = move_to_first_node( reader ); success = move_to_first_node( &reader->current );
break; break;
case WS_MOVE_TO_NEXT_NODE: case WS_MOVE_TO_NEXT_NODE:
success = move_to_next_node( reader ); success = move_to_next_node( &reader->current );
break; break;
case WS_MOVE_TO_PREVIOUS_NODE: case WS_MOVE_TO_PREVIOUS_NODE:
success = move_to_prev_node( reader ); success = move_to_prev_node( &reader->current );
break; break;
case WS_MOVE_TO_CHILD_NODE: case WS_MOVE_TO_CHILD_NODE:
success = move_to_child_node( reader ); success = move_to_child_node( &reader->current );
break; break;
case WS_MOVE_TO_BOF: case WS_MOVE_TO_BOF:
reader->current = reader->root; success = move_to_bof( reader->root, &reader->current );
success = TRUE;
break; break;
case WS_MOVE_TO_EOF: case WS_MOVE_TO_EOF:
if ((ptr = list_tail( &reader->root->children ))) success = move_to_eof( reader->root, &reader->current );
{
reader->current = LIST_ENTRY( ptr, struct node, entry );
success = TRUE;
}
break; break;
default: default:
@ -3186,10 +3207,10 @@ static BOOL is_empty_text_node( const struct node *node )
static HRESULT read_next_node( struct reader *reader ) static HRESULT read_next_node( struct reader *reader )
{ {
if (reader->current == reader->last) return read_node( reader ); if (reader->current == reader->last) return read_node( reader );
if (move_to_child_node( reader )) return S_OK; if (move_to_child_node( &reader->current )) return S_OK;
if (move_to_next_node( reader )) return S_OK; if (move_to_next_node( &reader->current )) return S_OK;
if (!move_to_parent_node( reader )) return WS_E_INVALID_FORMAT; if (!move_to_parent_node( &reader->current )) return WS_E_INVALID_FORMAT;
if (move_to_next_node( reader )) return S_OK; if (move_to_next_node( &reader->current )) return S_OK;
return WS_E_INVALID_FORMAT; return WS_E_INVALID_FORMAT;
} }

View File

@ -1415,6 +1415,76 @@ static void test_complex_struct_type(void)
WsFreeHeap( heap ); 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) START_TEST(writer)
{ {
@ -1434,4 +1504,5 @@ START_TEST(writer)
test_WsWriteXmlnsAttribute(); test_WsWriteXmlnsAttribute();
test_WsGetPrefixFromNamespace(); test_WsGetPrefixFromNamespace();
test_complex_struct_type(); test_complex_struct_type();
test_WsMoveWriter();
} }

View File

@ -94,7 +94,7 @@
@ stub WsMarkHeaderAsUnderstood @ stub WsMarkHeaderAsUnderstood
@ stub WsMatchPolicyAlternative @ stub WsMatchPolicyAlternative
@ stdcall WsMoveReader(ptr long ptr ptr) @ stdcall WsMoveReader(ptr long ptr ptr)
@ stub WsMoveWriter @ stdcall WsMoveWriter(ptr long ptr ptr)
@ stdcall WsOpenChannel(ptr ptr ptr ptr) @ stdcall WsOpenChannel(ptr ptr ptr ptr)
@ stub WsOpenListener @ stub WsOpenListener
@ stub WsOpenServiceHost @ stub WsOpenServiceHost

View File

@ -52,6 +52,19 @@ static inline WS_XML_NODE_TYPE node_type( const struct node *node )
return node->hdr.node.nodeType; 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 struct prop_desc
{ {
ULONG size; ULONG size;

View File

@ -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; if (namespace_in_scope( &writer->current->hdr, prefix, ns )) return S_OK;
return write_add_namespace_attribute( writer, prefix, ns, single ); 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 );
}