[3/8] webservices: Keep track of the parent-child relationship between nodes.
Hans Leidekker
hans at codeweavers.com
Tue Nov 10 03:46:36 CST 2015
Signed-off-by: Hans Leidekker <hans at codeweavers.com>
---
dlls/webservices/reader.c | 223 +++++++++++++++++++++++++++++-----------------
1 file changed, 143 insertions(+), 80 deletions(-)
diff --git a/dlls/webservices/reader.c b/dlls/webservices/reader.c
index 4195184..48b9c01 100644
--- a/dlls/webservices/reader.c
+++ b/dlls/webservices/reader.c
@@ -253,7 +253,9 @@ void WINAPI WsFreeHeap( WS_HEAP *handle )
struct node
{
WS_XML_ELEMENT_NODE hdr;
- struct list entry;
+ struct list entry;
+ struct node *parent;
+ struct list children;
};
static struct node *alloc_node( WS_XML_NODE_TYPE type )
@@ -263,6 +265,7 @@ static struct node *alloc_node( WS_XML_NODE_TYPE type )
if (!(ret = heap_alloc_zero( sizeof(*ret) ))) return NULL;
ret->hdr.node.nodeType = type;
list_init( &ret->entry );
+ list_init( &ret->children );
return ret;
}
@@ -316,16 +319,18 @@ static void free_node( struct node *node )
heap_free( node );
}
-static void destroy_nodes( struct list *list )
+static void destroy_nodes( struct node *node )
{
struct list *ptr;
- while ((ptr = list_head( list )))
+ if (!node) return;
+ while ((ptr = list_head( &node->children )))
{
- struct node *node = LIST_ENTRY( ptr, struct node, entry );
- list_remove( &node->entry );
- free_node( node );
+ struct node *child = LIST_ENTRY( ptr, struct node, entry );
+ list_remove( &child->entry );
+ destroy_nodes( child );
}
+ free_node( node );
}
static const struct
@@ -369,7 +374,7 @@ struct reader
ULONG read_pos;
const char *read_bufptr;
enum reader_state state;
- struct list nodes;
+ struct node *root;
struct node *current;
WS_XML_READER_INPUT_TYPE input_type;
const char *input_data;
@@ -417,18 +422,45 @@ static HRESULT get_reader_prop( struct reader *reader, WS_XML_READER_PROPERTY_ID
return S_OK;
}
+static void read_insert_eof( struct reader *reader, struct node *eof )
+{
+ if (!reader->root) reader->root = eof;
+ else
+ {
+ eof->parent = reader->root;
+ list_add_tail( &reader->root->children, &eof->entry );
+ }
+ reader->current = eof;
+}
+
+static void read_insert_bof( struct reader *reader, struct node *bof )
+{
+ reader->root->parent = bof;
+ list_add_tail( &bof->children, &reader->root->entry );
+ reader->current = reader->root = bof;
+}
+
+static void read_insert_node( struct reader *reader, struct node *parent, struct node *node )
+{
+ node->parent = parent;
+ if (node->parent == reader->root)
+ {
+ struct list *eof = list_tail( &reader->root->children );
+ list_add_before( eof, &node->entry );
+ }
+ else list_add_tail( &parent->children, &node->entry );
+ reader->current = node;
+}
+
static HRESULT read_init_state( struct reader *reader )
{
struct node *node;
- list_init( &reader->nodes );
+ destroy_nodes( reader->root );
+ reader->root = NULL;
if (!(node = alloc_node( WS_XML_NODE_TYPE_EOF ))) return E_OUTOFMEMORY;
- list_add_tail( &reader->nodes, &node->entry );
- reader->current = node;
- reader->state = READER_STATE_INITIAL;
- reader->read_size = 0;
- reader->read_pos = 0;
- reader->read_bufptr = NULL;
+ read_insert_eof( reader, node );
+ reader->state = READER_STATE_INITIAL;
return S_OK;
}
@@ -486,7 +518,7 @@ void WINAPI WsFreeReader( WS_XML_READER *handle )
TRACE( "%p\n", handle );
if (!reader) return;
- destroy_nodes( &reader->nodes );
+ destroy_nodes( reader->root );
heap_free( reader );
}
@@ -848,7 +880,8 @@ static HRESULT read_element( struct reader *reader )
if (read_end_of_data( reader ))
{
- reader->current = LIST_ENTRY( list_tail( &reader->nodes ), struct node, entry );
+ struct list *eof = list_tail( &reader->root->children );
+ reader->current = LIST_ENTRY( eof, struct node, entry );
reader->state = READER_STATE_EOF;
return S_OK;
}
@@ -893,11 +926,11 @@ static HRESULT read_element( struct reader *reader )
hr = WS_E_INVALID_FORMAT;
goto error;
}
+
+ read_insert_node( reader, reader->current, node );
read_skip( reader, 1 );
+ reader->state = READER_STATE_STARTELEMENT;
- list_add_after( &reader->current->entry, &node->entry );
- reader->current = node;
- reader->state = READER_STATE_STARTELEMENT;
return S_OK;
error:
@@ -932,9 +965,8 @@ static HRESULT read_text( struct reader *reader )
}
text->text = (WS_XML_TEXT *)utf8;
- list_add_after( &reader->current->entry, &node->entry );
- reader->current = node;
- reader->state = READER_STATE_TEXT;
+ read_insert_node( reader, reader->current, node );
+ reader->state = READER_STATE_TEXT;
return S_OK;
}
@@ -951,10 +983,9 @@ static HRESULT read_to_startelement( struct reader *reader, BOOL *found )
switch (reader->state)
{
case READER_STATE_INITIAL:
- {
if ((hr = read_xmldecl( reader )) != S_OK) return hr;
break;
- }
+
case READER_STATE_STARTELEMENT:
if (found) *found = TRUE;
return S_OK;
@@ -975,16 +1006,48 @@ static HRESULT read_to_startelement( struct reader *reader, BOOL *found )
return hr;
}
+static BOOL cmp_localname( const char *name1, ULONG len1, const char *name2, ULONG len2 )
+{
+ ULONG i;
+ if (len1 != len2) return FALSE;
+ for (i = 0; i < len1; i++) { if (toupper( name1[i] ) != toupper( name2[i] )) return FALSE; }
+ return TRUE;
+}
+
+static struct node *find_parent_element( struct node *node, const char *localname, ULONG len )
+{
+ struct node *parent;
+ WS_XML_STRING *name;
+
+ for (parent = node; parent; parent = parent->parent)
+ {
+ if (parent->hdr.node.nodeType != WS_XML_NODE_TYPE_ELEMENT) continue;
+ name = ((WS_XML_ELEMENT_NODE *)parent)->localName;
+ if (!cmp_localname( (const char *)name->bytes, name->length, localname, len )) continue;
+ return parent;
+ }
+ return NULL;
+}
+
static HRESULT read_endelement( struct reader *reader )
{
- struct node *node;
- unsigned int ch, skip;
+ struct node *node, *parent;
+ unsigned int len = 0, ch, skip;
+ const char *start;
- if (reader->state != READER_STATE_TEXT) return WS_E_INVALID_FORMAT;
+ switch (reader->state)
+ {
+ case READER_STATE_TEXT:
+ case READER_STATE_STARTELEMENT:
+ break;
+ default:
+ return WS_E_INVALID_FORMAT;
+ }
if (read_cmp( reader, "</", 2 )) return WS_E_INVALID_FORMAT;
read_skip( reader, 2 );
+ start = read_current_ptr( reader );
for (;;)
{
if (!(ch = read_utf8_char( reader, &skip ))) return WS_E_INVALID_FORMAT;
@@ -995,12 +1058,14 @@ static HRESULT read_endelement( struct reader *reader )
}
if (!read_isnamechar( ch )) return WS_E_INVALID_FORMAT;
read_skip( reader, skip );
+ len += skip;
}
+ if (!(parent = find_parent_element( reader->current, start, len )))
+ return WS_E_INVALID_FORMAT;
if (!(node = alloc_node( WS_XML_NODE_TYPE_END_ELEMENT ))) return E_OUTOFMEMORY;
- list_add_after( &reader->current->entry, &node->entry );
- reader->current = node;
- reader->state = READER_STATE_ENDELEMENT;
+ read_insert_node( reader, parent, node );
+ reader->state = READER_STATE_ENDELEMENT;
return S_OK;
}
@@ -1037,9 +1102,8 @@ static HRESULT read_comment( struct reader *reader )
memcpy( comment->value.bytes, start, len );
comment->value.length = len;
- list_add_after( &reader->current->entry, &node->entry );
- reader->current = node;
- reader->state = READER_STATE_COMMENT;
+ read_insert_node( reader, reader->current, node );
+ reader->state = READER_STATE_COMMENT;
return S_OK;
}
@@ -1051,7 +1115,8 @@ static HRESULT read_node( struct reader *reader )
{
if (read_end_of_data( reader ))
{
- reader->current = LIST_ENTRY( list_tail( &reader->nodes ), struct node, entry );
+ struct list *eof = list_tail( &reader->root->children );
+ reader->current = LIST_ENTRY( eof, struct node, entry );
reader->state = READER_STATE_EOF;
return S_OK;
}
@@ -1447,6 +1512,17 @@ static WS_CHARSET detect_charset( const unsigned char *data, ULONG size, ULONG *
return ret;
}
+static void set_input_buffer( struct reader *reader, const char *data, ULONG size )
+{
+ reader->input_type = WS_XML_READER_INPUT_TYPE_BUFFER;
+ reader->input_data = data;
+ reader->input_size = size;
+
+ reader->read_size = reader->input_size;
+ reader->read_pos = 0;
+ reader->read_bufptr = reader->input_data;
+}
+
/**************************************************************************
* WsSetInput [webservices.@]
*/
@@ -1470,55 +1546,48 @@ HRESULT WINAPI WsSetInput( WS_XML_READER *handle, const WS_XML_READER_ENCODING *
if (hr != S_OK) return hr;
}
- destroy_nodes( &reader->nodes );
if ((hr = read_init_state( reader )) != S_OK) return hr;
- if (!(node = alloc_node( WS_XML_NODE_TYPE_BOF ))) return E_OUTOFMEMORY;
- list_add_head( &reader->nodes, &node->entry );
- reader->current = node;
-
switch (encoding->encodingType)
{
- case WS_XML_READER_ENCODING_TYPE_TEXT:
- {
- WS_XML_READER_TEXT_ENCODING *text = (WS_XML_READER_TEXT_ENCODING *)encoding;
- WS_XML_READER_BUFFER_INPUT *buf = (WS_XML_READER_BUFFER_INPUT *)input;
- WS_CHARSET charset = text->charSet;
+ case WS_XML_READER_ENCODING_TYPE_TEXT:
+ {
+ WS_XML_READER_TEXT_ENCODING *text = (WS_XML_READER_TEXT_ENCODING *)encoding;
+ WS_XML_READER_BUFFER_INPUT *buf = (WS_XML_READER_BUFFER_INPUT *)input;
+ WS_CHARSET charset = text->charSet;
- if (input->inputType != WS_XML_READER_INPUT_TYPE_BUFFER)
- {
- FIXME( "charset detection on input type %u not supported\n", input->inputType );
- return E_NOTIMPL;
- }
+ if (input->inputType != WS_XML_READER_INPUT_TYPE_BUFFER)
+ {
+ FIXME( "charset detection on input type %u not supported\n", input->inputType );
+ return E_NOTIMPL;
+ }
- if (charset == WS_CHARSET_AUTO)
- charset = detect_charset( buf->encodedData, buf->encodedDataSize, &offset );
+ if (charset == WS_CHARSET_AUTO)
+ charset = detect_charset( buf->encodedData, buf->encodedDataSize, &offset );
- hr = set_reader_prop( reader, WS_XML_READER_PROPERTY_CHARSET, &charset, sizeof(charset) );
- if (hr != S_OK) return hr;
- break;
- }
- default:
- FIXME( "encoding type %u not supported\n", encoding->encodingType );
- return E_NOTIMPL;
+ hr = set_reader_prop( reader, WS_XML_READER_PROPERTY_CHARSET, &charset, sizeof(charset) );
+ if (hr != S_OK) return hr;
+ break;
+ }
+ default:
+ FIXME( "encoding type %u not supported\n", encoding->encodingType );
+ return E_NOTIMPL;
}
switch (input->inputType)
{
- case WS_XML_READER_INPUT_TYPE_BUFFER:
- {
- WS_XML_READER_BUFFER_INPUT *buf = (WS_XML_READER_BUFFER_INPUT *)input;
-
- reader->input_type = WS_XML_READER_INPUT_TYPE_BUFFER;
- reader->input_data = (const char *)buf->encodedData + offset;
- reader->input_size = buf->encodedDataSize - offset;
- reader->read_bufptr = reader->input_data;
- break;
- }
- default:
- FIXME( "input type %u not supported\n", input->inputType );
- return E_NOTIMPL;
+ case WS_XML_READER_INPUT_TYPE_BUFFER:
+ {
+ WS_XML_READER_BUFFER_INPUT *buf = (WS_XML_READER_BUFFER_INPUT *)input;
+ set_input_buffer( reader, (const char *)buf->encodedData + offset, buf->encodedDataSize - offset );
+ break;
+ }
+ default:
+ FIXME( "input type %u not supported\n", input->inputType );
+ return E_NOTIMPL;
}
+ if (!(node = alloc_node( WS_XML_NODE_TYPE_BOF ))) return E_OUTOFMEMORY;
+ read_insert_bof( reader, node );
return S_OK;
}
@@ -1547,21 +1616,15 @@ HRESULT WINAPI WsSetInputToBuffer( WS_XML_READER *handle, WS_XML_BUFFER *buffer,
if (hr != S_OK) return hr;
}
- destroy_nodes( &reader->nodes );
if ((hr = read_init_state( reader )) != S_OK) return hr;
- if (!(node = alloc_node( WS_XML_NODE_TYPE_BOF ))) return E_OUTOFMEMORY;
- list_add_head( &reader->nodes, &node->entry );
- reader->current = node;
-
charset = detect_charset( xmlbuf->ptr, xmlbuf->size, &offset );
hr = set_reader_prop( reader, WS_XML_READER_PROPERTY_CHARSET, &charset, sizeof(charset) );
if (hr != S_OK) return hr;
- reader->input_type = WS_XML_READER_INPUT_TYPE_BUFFER;
- reader->input_data = (const char *)xmlbuf->ptr + offset;
- reader->input_size = xmlbuf->size - offset;
- reader->read_bufptr = reader->input_data;
+ set_input_buffer( reader, (const char *)xmlbuf->ptr + offset, xmlbuf->size - offset );
+ if (!(node = alloc_node( WS_XML_NODE_TYPE_BOF ))) return E_OUTOFMEMORY;
+ read_insert_bof( reader, node );
return S_OK;
}
--
2.6.2
More information about the wine-patches
mailing list