webservices: Implement WsMoveWriter.
Signed-off-by: Hans Leidekker <hans@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
f5c8f69725
commit
768197795d
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue