[6/6] webservices: Add support for reading WS_XML_QNAME values.
Hans Leidekker
hans at codeweavers.com
Wed Jun 21 02:37:42 CDT 2017
Signed-off-by: Hans Leidekker <hans at codeweavers.com>
---
dlls/webservices/reader.c | 336 ++++++++++++++++++++++------------------
dlls/webservices/tests/reader.c | 27 ++++
2 files changed, 216 insertions(+), 147 deletions(-)
diff --git a/dlls/webservices/reader.c b/dlls/webservices/reader.c
index dbe993b..798bd4f 100644
--- a/dlls/webservices/reader.c
+++ b/dlls/webservices/reader.c
@@ -958,47 +958,53 @@ HRESULT append_attribute( WS_XML_ELEMENT_NODE *elem, WS_XML_ATTRIBUTE *attr )
return S_OK;
}
-static HRESULT split_name( const unsigned char *str, ULONG len, const unsigned char **prefix,
- ULONG *prefix_len, const unsigned char **localname, ULONG *localname_len )
+static inline void init_xml_string( BYTE *bytes, ULONG len, WS_XML_STRING *str )
{
- const unsigned char *ptr = str;
-
- *prefix = NULL;
- *prefix_len = 0;
+ str->length = len;
+ str->bytes = bytes;
+ str->dictionary = NULL;
+ str->id = 0;
+}
- *localname = str;
- *localname_len = len;
+static HRESULT split_qname( const BYTE *str, ULONG len, WS_XML_STRING *prefix, WS_XML_STRING *localname )
+{
+ BYTE *prefix_bytes = NULL, *localname_bytes = (BYTE *)str, *ptr = (BYTE *)str;
+ ULONG prefix_len = 0, localname_len = len;
while (len--)
{
if (*ptr == ':')
{
if (ptr == str) return WS_E_INVALID_FORMAT;
- *prefix = str;
- *prefix_len = ptr - str;
- *localname = ptr + 1;
- *localname_len = len;
+ prefix_bytes = (BYTE *)str;
+ prefix_len = ptr - str;
+ localname_bytes = ptr + 1;
+ localname_len = len;
break;
}
ptr++;
}
+ if (!localname_len) return WS_E_INVALID_FORMAT;
+
+ init_xml_string( prefix_bytes, prefix_len, prefix );
+ init_xml_string( localname_bytes, localname_len, localname );
return S_OK;
}
-static HRESULT parse_name( const unsigned char *str, ULONG len, WS_XML_STRING **prefix, WS_XML_STRING **localname )
+static HRESULT parse_qname( const BYTE *str, ULONG len, WS_XML_STRING **prefix_ret, WS_XML_STRING **localname_ret )
{
- const unsigned char *localname_ptr, *prefix_ptr;
- ULONG localname_len, prefix_len;
+ WS_XML_STRING prefix, localname;
HRESULT hr;
- if ((hr = split_name( str, len, &prefix_ptr, &prefix_len, &localname_ptr, &localname_len )) != S_OK) return hr;
- if (!(*prefix = alloc_xml_string( prefix_ptr, prefix_len ))) return E_OUTOFMEMORY;
- if (!(*localname = alloc_xml_string( localname_ptr, localname_len )))
+ if ((hr = split_qname( str, len, &prefix, &localname )) != S_OK) return hr;
+ if (!(*prefix_ret = alloc_xml_string( NULL, prefix.length ))) return E_OUTOFMEMORY;
+ if (!(*localname_ret = dup_xml_string( &localname )))
{
- free_xml_string( *prefix );
- *prefix = NULL;
+ free_xml_string( *prefix_ret );
return E_OUTOFMEMORY;
}
+ memcpy( (*prefix_ret)->bytes, prefix.bytes, prefix.length );
+ if (prefix.length && add_xml_string( *prefix_ret ) != S_OK) WARN( "prefix not added to dictionary\n" );
return S_OK;
}
@@ -1508,7 +1514,7 @@ static HRESULT read_attribute_text( struct reader *reader, WS_XML_ATTRIBUTE **re
}
if (!len) goto error;
- if ((hr = parse_name( start, len, &prefix, &localname )) != S_OK) goto error;
+ if ((hr = parse_qname( start, len, &prefix, &localname )) != S_OK) goto error;
if (WsXmlStringEquals( prefix, &xmlns, NULL ) == S_OK)
{
free_xml_string( prefix );
@@ -1692,7 +1698,7 @@ static HRESULT set_namespaces( struct reader *reader, WS_XML_ELEMENT_NODE *elem
WS_XML_ATTRIBUTE *attr = elem->attributes[i];
if (attr->isXmlNs || WsXmlStringEquals( attr->prefix, &xml, NULL ) == S_OK) continue;
if (!(ns = get_namespace( reader, attr->prefix ))) return WS_E_INVALID_FORMAT;
- if (!(attr->ns = alloc_xml_string( NULL, ns->length ))) return E_OUTOFMEMORY;
+ if (!(attr->ns = alloc_xml_string( NULL, ns->length ))) return E_OUTOFMEMORY;
if (attr->ns->length) memcpy( attr->ns->bytes, ns->bytes, ns->length );
}
return S_OK;
@@ -1771,8 +1777,7 @@ static HRESULT read_element_text( struct reader *reader )
if (!len) goto error;
if (!(parent = find_parent( reader ))) goto error;
- if ((hr = parse_name( start, len, &elem->prefix, &elem->localName )) != S_OK) goto error;
-
+ if ((hr = parse_qname( start, len, &elem->prefix, &elem->localName )) != S_OK) goto error;
if ((hr = read_attributes_text( reader, elem )) != S_OK) goto error;
if ((hr = set_namespaces( reader, elem )) != S_OK) goto error;
@@ -2301,7 +2306,7 @@ static HRESULT read_endelement_text( struct reader *reader )
struct node *parent;
unsigned int len = 0, ch, skip;
const unsigned char *start;
- WS_XML_STRING *prefix, *localname;
+ WS_XML_STRING prefix, localname;
HRESULT hr;
if (read_cmp( reader, "</", 2 )) return WS_E_INVALID_FORMAT;
@@ -2321,11 +2326,8 @@ static HRESULT read_endelement_text( struct reader *reader )
len += skip;
}
- if ((hr = parse_name( start, len, &prefix, &localname )) != S_OK) return hr;
- parent = find_startelement( reader, prefix, localname );
- free_xml_string( prefix );
- free_xml_string( localname );
- if (!parent) return WS_E_INVALID_FORMAT;
+ if ((hr = split_qname( start, len, &prefix, &localname )) != S_OK) return hr;
+ if (!(parent = find_startelement( reader, &prefix, &localname ))) return WS_E_INVALID_FORMAT;
reader->current = LIST_ENTRY( list_tail( &parent->children ), struct node, entry );
reader->last = reader->current;
@@ -3163,123 +3165,6 @@ HRESULT WINAPI WsReadEndAttribute( WS_XML_READER *handle, WS_ERROR *error )
return S_OK;
}
-static HRESULT find_namespace( struct reader *reader, const WS_XML_STRING *prefix, const WS_XML_STRING **ns )
-{
- const struct node *node;
- for (node = reader->current->parent; node_type( node ) == WS_XML_NODE_TYPE_ELEMENT; node = node->parent)
- {
- const WS_XML_ELEMENT_NODE *elem = &node->hdr;
- ULONG i;
- for (i = 0; i < elem->attributeCount; i++)
- {
- if (!elem->attributes[i]->isXmlNs) continue;
- if (WsXmlStringEquals( elem->attributes[i]->prefix, prefix, NULL ) != S_OK) continue;
- *ns = elem->attributes[i]->ns;
- return S_OK;
- }
- }
- return WS_E_INVALID_FORMAT;
-}
-
-static HRESULT read_qualified_name( struct reader *reader, WS_HEAP *heap, WS_XML_STRING *prefix_ret,
- WS_XML_STRING *localname_ret, WS_XML_STRING *ns_ret )
-{
- const WS_XML_TEXT_NODE *node = (const WS_XML_TEXT_NODE *)reader->current;
- const WS_XML_UTF8_TEXT *utf8 = (const WS_XML_UTF8_TEXT *)node->text;
- unsigned char *prefix_bytes, *localname_bytes, *ns_bytes;
- const unsigned char *ptr = utf8->value.bytes;
- WS_XML_STRING prefix, localname, empty = {0, NULL};
- const WS_XML_STRING *ns = ∅
- ULONG len = utf8->value.length;
- HRESULT hr;
-
- while (len && read_isspace( *ptr )) { ptr++; len--; }
- while (len && read_isspace( ptr[len - 1] )) { len--; }
- if (!len) return WS_E_INVALID_FORMAT;
-
- if ((hr = split_name( ptr, len, (const unsigned char **)&prefix.bytes, &prefix.length,
- (const unsigned char **)&localname.bytes, &localname.length )) != S_OK) return hr;
-
- if (!localname.length) return WS_E_INVALID_FORMAT;
- if (prefix.length && (hr = find_namespace( reader, &prefix, &ns )) != S_OK) return hr;
-
- if (!(prefix_bytes = ws_alloc( heap, prefix.length ))) return WS_E_QUOTA_EXCEEDED;
- memcpy( prefix_bytes, prefix.bytes, prefix.length );
-
- if (!(localname_bytes = ws_alloc( heap, localname.length )))
- {
- ws_free( heap, prefix_bytes, prefix.length );
- return WS_E_QUOTA_EXCEEDED;
- }
- memcpy( localname_bytes, localname.bytes, localname.length );
-
- if (!(ns_bytes = ws_alloc( heap, ns->length )))
- {
- ws_free( heap, prefix_bytes, prefix.length );
- ws_free( heap, localname_bytes, localname.length );
- return WS_E_QUOTA_EXCEEDED;
- }
- memcpy( ns_bytes, ns->bytes, ns->length );
-
- prefix_ret->bytes = prefix_bytes;
- prefix_ret->length = prefix.length;
-
- localname_ret->bytes = localname_bytes;
- localname_ret->length = localname.length;
-
- ns_ret->bytes = ns_bytes;
- ns_ret->length = ns->length;
-
- return S_OK;
-}
-
-/**************************************************************************
- * WsReadQualifiedName [webservices.@]
- */
-HRESULT WINAPI WsReadQualifiedName( WS_XML_READER *handle, WS_HEAP *heap, WS_XML_STRING *prefix,
- WS_XML_STRING *localname, WS_XML_STRING *ns,
- WS_ERROR *error )
-{
- struct reader *reader = (struct reader *)handle;
- HRESULT hr;
-
- TRACE( "%p %p %p %p %p %p\n", handle, heap, prefix, localname, ns, error );
- if (error) FIXME( "ignoring error parameter\n" );
-
- if (!reader || !heap) return E_INVALIDARG;
-
- EnterCriticalSection( &reader->cs );
-
- if (reader->magic != READER_MAGIC)
- {
- LeaveCriticalSection( &reader->cs );
- return E_INVALIDARG;
- }
-
- if (!reader->input_type)
- {
- LeaveCriticalSection( &reader->cs );
- return WS_E_INVALID_OPERATION;
- }
-
- if (!localname)
- {
- LeaveCriticalSection( &reader->cs );
- return E_INVALIDARG;
- }
-
- if (reader->state != READER_STATE_TEXT)
- {
- LeaveCriticalSection( &reader->cs );
- return WS_E_INVALID_FORMAT;
- }
-
- hr = read_qualified_name( reader, heap, prefix, localname, ns );
-
- LeaveCriticalSection( &reader->cs );
- return hr;
-}
-
static WCHAR *xmltext_to_widechar( WS_HEAP *heap, const WS_XML_TEXT *text )
{
WCHAR *ret;
@@ -3675,6 +3560,98 @@ static HRESULT str_to_xml_string( const unsigned char *str, ULONG len, WS_HEAP *
return S_OK;
}
+static HRESULT copy_xml_string( WS_HEAP *heap, const WS_XML_STRING *src, WS_XML_STRING *dst )
+{
+ if (!(dst->bytes = ws_alloc( heap, src->length ))) return WS_E_QUOTA_EXCEEDED;
+ memcpy( dst->bytes, src->bytes, src->length );
+ dst->length = src->length;
+ return S_OK;
+}
+
+static HRESULT str_to_qname( struct reader *reader, const unsigned char *str, ULONG len, WS_HEAP *heap,
+ WS_XML_STRING *prefix_ret, WS_XML_STRING *localname_ret, WS_XML_STRING *ns_ret )
+{
+ const unsigned char *p = str;
+ WS_XML_STRING prefix, localname;
+ const WS_XML_STRING *ns;
+ HRESULT hr;
+
+ while (len && read_isspace( *p )) { p++; len--; }
+ while (len && read_isspace( p[len - 1] )) { len--; }
+
+ if ((hr = split_qname( p, len, &prefix, &localname )) != S_OK) return hr;
+ if (!(ns = get_namespace( reader, &prefix ))) return WS_E_INVALID_FORMAT;
+
+ if (prefix_ret && (hr = copy_xml_string( heap, &prefix, prefix_ret )) != S_OK) return hr;
+ if ((hr = copy_xml_string( heap, &localname, localname_ret )) != S_OK)
+ {
+ ws_free( heap, prefix_ret->bytes, prefix_ret->length );
+ return hr;
+ }
+ if ((hr = copy_xml_string( heap, ns, ns_ret )) != S_OK)
+ {
+ ws_free( heap, prefix_ret->bytes, prefix_ret->length );
+ ws_free( heap, localname_ret->bytes, localname_ret->length );
+ return hr;
+ }
+ return S_OK;
+}
+
+static HRESULT read_qualified_name( struct reader *reader, WS_HEAP *heap, WS_XML_STRING *prefix,
+ WS_XML_STRING *localname, WS_XML_STRING *ns )
+{
+ const WS_XML_TEXT_NODE *node = (const WS_XML_TEXT_NODE *)reader->current;
+ const WS_XML_UTF8_TEXT *utf8 = (const WS_XML_UTF8_TEXT *)node->text;
+ return str_to_qname( reader, utf8->value.bytes, utf8->value.length, heap, prefix, localname, ns );
+}
+
+/**************************************************************************
+ * WsReadQualifiedName [webservices.@]
+ */
+HRESULT WINAPI WsReadQualifiedName( WS_XML_READER *handle, WS_HEAP *heap, WS_XML_STRING *prefix,
+ WS_XML_STRING *localname, WS_XML_STRING *ns,
+ WS_ERROR *error )
+{
+ struct reader *reader = (struct reader *)handle;
+ HRESULT hr;
+
+ TRACE( "%p %p %p %p %p %p\n", handle, heap, prefix, localname, ns, error );
+ if (error) FIXME( "ignoring error parameter\n" );
+
+ if (!reader || !heap) return E_INVALIDARG;
+
+ EnterCriticalSection( &reader->cs );
+
+ if (reader->magic != READER_MAGIC)
+ {
+ LeaveCriticalSection( &reader->cs );
+ return E_INVALIDARG;
+ }
+
+ if (!reader->input_type)
+ {
+ LeaveCriticalSection( &reader->cs );
+ return WS_E_INVALID_OPERATION;
+ }
+
+ if (!localname)
+ {
+ LeaveCriticalSection( &reader->cs );
+ return E_INVALIDARG;
+ }
+
+ if (reader->state != READER_STATE_TEXT)
+ {
+ LeaveCriticalSection( &reader->cs );
+ return WS_E_INVALID_FORMAT;
+ }
+
+ hr = read_qualified_name( reader, heap, prefix, localname, ns );
+
+ LeaveCriticalSection( &reader->cs );
+ return hr;
+}
+
static const int month_offsets[2][12] =
{
{0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334},
@@ -4946,6 +4923,62 @@ static HRESULT read_type_xml_string( struct reader *reader, WS_TYPE_MAPPING mapp
return S_OK;
}
+static HRESULT read_type_qname( struct reader *reader, WS_TYPE_MAPPING mapping,
+ const WS_XML_STRING *localname, const WS_XML_STRING *ns,
+ const WS_XML_QNAME_DESCRIPTION *desc, WS_READ_OPTION option,
+ WS_HEAP *heap, void *ret, ULONG size )
+{
+ WS_XML_UTF8_TEXT *utf8;
+ WS_XML_QNAME val = {{0}};
+ HRESULT hr;
+ BOOL found;
+
+ if (desc) FIXME( "ignoring description\n" );
+
+ if (node_type( reader->current ) != WS_XML_NODE_TYPE_ELEMENT) return WS_E_INVALID_FORMAT;
+ if ((hr = read_startelement( reader )) != S_OK) return hr;
+ if (node_type( reader->current ) != WS_XML_NODE_TYPE_TEXT) return WS_E_INVALID_FORMAT;
+
+ if ((hr = read_get_text( reader, mapping, localname, ns, &utf8, &found )) != S_OK) return hr;
+ if (found && (hr = str_to_qname( reader, utf8->value.bytes, utf8->value.length, heap,
+ NULL, &val.localName, &val.ns )) != S_OK) return hr;
+
+ switch (option)
+ {
+ case WS_READ_REQUIRED_VALUE:
+ if (!found) return WS_E_INVALID_FORMAT;
+ /* fall through */
+
+ case WS_READ_NILLABLE_VALUE:
+ if (size != sizeof(val)) return E_INVALIDARG;
+ *(WS_XML_QNAME *)ret = val;
+ break;
+
+ case WS_READ_REQUIRED_POINTER:
+ if (!found) return WS_E_INVALID_FORMAT;
+ /* fall through */
+
+ case WS_READ_OPTIONAL_POINTER:
+ case WS_READ_NILLABLE_POINTER:
+ {
+ WS_XML_QNAME *heap_val = NULL;
+ if (size != sizeof(heap_val)) return E_INVALIDARG;
+ if (found)
+ {
+ if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
+ *heap_val = val;
+ }
+ *(WS_XML_QNAME **)ret = heap_val;
+ break;
+ }
+ default:
+ FIXME( "read option %u not supported\n", option );
+ return E_NOTIMPL;
+ }
+
+ return S_OK;
+}
+
static BOOL is_empty_text_node( const struct node *node )
{
const WS_XML_TEXT_NODE *text = (const WS_XML_TEXT_NODE *)node;
@@ -5069,6 +5102,9 @@ ULONG get_type_size( WS_TYPE type, const WS_STRUCT_DESCRIPTION *desc )
case WS_XML_STRING_TYPE:
return sizeof(WS_XML_STRING);
+ case WS_XML_QNAME_TYPE:
+ return sizeof(WS_XML_QNAME);
+
case WS_STRUCT_TYPE:
return desc->size;
@@ -5108,6 +5144,7 @@ static WS_READ_OPTION get_field_read_option( WS_TYPE type, ULONG options )
case WS_STRING_TYPE:
case WS_BYTES_TYPE:
case WS_XML_STRING_TYPE:
+ case WS_XML_QNAME_TYPE:
case WS_STRUCT_TYPE:
case WS_ENUM_TYPE:
if (options & (WS_FIELD_OPTIONAL|WS_FIELD_NILLABLE)) return WS_READ_NILLABLE_VALUE;
@@ -5537,6 +5574,11 @@ static HRESULT read_type( struct reader *reader, WS_TYPE_MAPPING mapping, WS_TYP
return hr;
break;
+ case WS_XML_QNAME_TYPE:
+ if ((hr = read_type_qname( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
+ return hr;
+ break;
+
case WS_STRUCT_TYPE:
if ((hr = read_type_struct( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
return hr;
diff --git a/dlls/webservices/tests/reader.c b/dlls/webservices/tests/reader.c
index d528eca..fc1efeb 100644
--- a/dlls/webservices/tests/reader.c
+++ b/dlls/webservices/tests/reader.c
@@ -1397,6 +1397,7 @@ static void test_WsReadType(void)
WS_BYTES val_bytes;
WS_STRING val_string;
WS_UNIQUE_ID val_id;
+ WS_XML_QNAME val_qname;
hr = WsCreateHeap( 1 << 16, 0, NULL, 0, &heap, NULL );
ok( hr == S_OK, "got %08x\n", hr );
@@ -1731,6 +1732,32 @@ static void test_WsReadType(void)
ok( val_id.uri.chars == NULL, "chars set %s\n", wine_dbgstr_wn(val_id.uri.chars, val_id.uri.length) );
ok( IsEqualGUID( &val_id.guid, &guid ), "wrong guid\n" );
+ memset( &val_qname, 0, sizeof(val_qname) );
+ hr = set_input( reader, "<t>u</t>", sizeof("<t>u</t>") - 1 );
+ ok( hr == S_OK, "got %08x\n", hr );
+ hr = WsReadToStartElement( reader, NULL, NULL, NULL, NULL );
+ ok( hr == S_OK, "got %08x\n", hr );
+ hr = WsReadType( reader, WS_ELEMENT_TYPE_MAPPING, WS_XML_QNAME_TYPE, NULL,
+ WS_READ_REQUIRED_VALUE, heap, &val_qname, sizeof(val_qname), NULL );
+ ok( hr == S_OK, "got %08x\n", hr );
+ ok( val_qname.localName.length == 1, "got %u\n", val_qname.localName.length );
+ ok( val_qname.localName.bytes[0] == 'u', "wrong data\n" );
+ ok( !val_qname.ns.length, "got %u\n", val_qname.ns.length );
+ ok( val_qname.ns.bytes != NULL, "bytes not set\n" );
+
+ memset( &val_qname, 0, sizeof(val_qname) );
+ hr = set_input( reader, "<p:t xmlns:p=\"ns\"> p:u </p:t>", sizeof("<p:t xmlns:p=\"ns\"> p:u </p:t>") - 1 );
+ ok( hr == S_OK, "got %08x\n", hr );
+ hr = WsReadToStartElement( reader, NULL, NULL, NULL, NULL );
+ ok( hr == S_OK, "got %08x\n", hr );
+ hr = WsReadType( reader, WS_ELEMENT_TYPE_MAPPING, WS_XML_QNAME_TYPE, NULL,
+ WS_READ_REQUIRED_VALUE, heap, &val_qname, sizeof(val_qname), NULL );
+ ok( hr == S_OK, "got %08x\n", hr );
+ ok( val_qname.localName.length == 1, "got %u\n", val_qname.localName.length );
+ ok( val_qname.localName.bytes[0] == 'u', "wrong data\n" );
+ ok( val_qname.ns.length == 2, "got %u\n", val_qname.ns.length );
+ ok( !memcmp( val_qname.ns.bytes, "ns", 2 ), "wrong data\n" );
+
WsFreeReader( reader );
WsFreeHeap( heap );
}
--
2.1.4
More information about the wine-patches
mailing list