[3/6] webservices: Implement WsReadQualifiedName.
Hans Leidekker
hans at codeweavers.com
Fri Apr 28 05:12:48 CDT 2017
Signed-off-by: Hans Leidekker <hans at codeweavers.com>
---
dlls/webservices/reader.c | 158 +++++++++++++++++++++++++++++++++++---
dlls/webservices/tests/reader.c | 112 +++++++++++++++++++++++++++
dlls/webservices/webservices.spec | 2 +-
include/webservices.h | 2 +
4 files changed, 262 insertions(+), 12 deletions(-)
diff --git a/dlls/webservices/reader.c b/dlls/webservices/reader.c
index 6d15002d00..9b0fd60b3b 100644
--- a/dlls/webservices/reader.c
+++ b/dlls/webservices/reader.c
@@ -966,27 +966,45 @@ HRESULT append_attribute( WS_XML_ELEMENT_NODE *elem, WS_XML_ATTRIBUTE *attr )
return S_OK;
}
-static HRESULT parse_name( const unsigned char *str, unsigned int len,
- WS_XML_STRING **prefix, WS_XML_STRING **localname )
+static HRESULT split_name( const unsigned char *str, ULONG len, const unsigned char **prefix,
+ ULONG *prefix_len, const unsigned char **localname, ULONG *localname_len )
{
- const unsigned char *name_ptr = str, *prefix_ptr = NULL;
- unsigned int i, name_len = len, prefix_len = 0;
+ const unsigned char *ptr = str;
+
+ *prefix = NULL;
+ *prefix_len = 0;
+
+ *localname = str;
+ *localname_len = len;
- for (i = 0; i < len; i++)
+ while (len--)
{
- if (str[i] == ':')
+ if (*ptr == ':')
{
- prefix_ptr = str;
- prefix_len = i;
- name_ptr = &str[i + 1];
- name_len -= i + 1;
+ if (ptr == str) return WS_E_INVALID_FORMAT;
+ *prefix = str;
+ *prefix_len = ptr - str;
+ *localname = ptr + 1;
+ *localname_len = len;
break;
}
+ ptr++;
}
+ return S_OK;
+}
+
+static HRESULT parse_name( const unsigned char *str, ULONG len, WS_XML_STRING **prefix, WS_XML_STRING **localname )
+{
+ const unsigned char *localname_ptr, *prefix_ptr;
+ ULONG localname_len, prefix_len;
+ 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( name_ptr, name_len )))
+ if (!(*localname = alloc_xml_string( localname_ptr, localname_len )))
{
heap_free( *prefix );
+ *prefix = NULL;
return E_OUTOFMEMORY;
}
return S_OK;
@@ -2116,6 +2134,124 @@ 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 %s %s %s %p\n", handle, heap, debugstr_xmlstr(prefix), debugstr_xmlstr(localname),
+ debugstr_xmlstr(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;
diff --git a/dlls/webservices/tests/reader.c b/dlls/webservices/tests/reader.c
index c10b5819ca..1fe37c5ed4 100644
--- a/dlls/webservices/tests/reader.c
+++ b/dlls/webservices/tests/reader.c
@@ -4240,6 +4240,117 @@ static void test_WsReadCharsUtf8(void)
WsFreeReader( reader );
}
+static void test_WsReadQualifiedName(void)
+{
+ static const char utf8[] = {'<','a','>',0xc3,0xab,'<','/','a','>',0};
+ static const char localname_utf8[] = {0xc3,0xab,0};
+ WS_XML_STRING prefix, localname, ns;
+ WS_XML_READER *reader;
+ WS_HEAP *heap;
+ HRESULT hr;
+ BOOL found;
+ ULONG i;
+ static const struct
+ {
+ const char *str;
+ HRESULT hr;
+ const char *prefix;
+ const char *localname;
+ const char *ns;
+ } tests[] =
+ {
+ { "<a></a>", WS_E_INVALID_FORMAT, NULL, NULL, NULL },
+ { "<a> </a>", WS_E_INVALID_FORMAT, NULL, NULL, NULL },
+ { "<a>:</a>", WS_E_INVALID_FORMAT, NULL, NULL, NULL },
+ { "<a>t</a>", S_OK, "", "t", "" },
+ { "<a>p:</a>", WS_E_INVALID_FORMAT, NULL, NULL, NULL },
+ { "<a>p:t</a>", WS_E_INVALID_FORMAT, NULL, NULL, NULL },
+ { "<a>:t</a>", WS_E_INVALID_FORMAT, NULL, NULL, NULL },
+ { "<a xmlns:p=\"ns\">p:t</a>", S_OK, "p", "t", "ns" },
+ { "<a xmlns:p=\"ns\">p:t:</a>", S_OK, "p", "t:", "ns" },
+ { "<a xmlns:p=\"ns\">p:</a>", WS_E_INVALID_FORMAT, NULL, NULL, NULL },
+ { "<a xmlns:p=\"ns\">:t</a>", WS_E_INVALID_FORMAT, NULL, NULL, NULL },
+ { "<a xmlns:p=\"ns\">:</a>", WS_E_INVALID_FORMAT, NULL, NULL, NULL },
+ { "<a xmlns:p=\"ns\">t</a>", S_OK, "", "t", "" },
+ { "<a xmlns:p=\"ns\"> </a>", WS_E_INVALID_FORMAT, NULL, NULL, NULL },
+ { "<a xmlns:p=\"ns\"></a>", WS_E_INVALID_FORMAT, NULL, NULL, NULL },
+ { "<a xmlns:p=\"ns\">p:t u</a>", S_OK, "p", "t u", "ns" },
+ { utf8, S_OK, "", localname_utf8, "" },
+ { "<a> t </a>", S_OK, "", "t", "" },
+ { "<a xmlns:p=\"ns\"> p:t</a>", S_OK, "p", "t", "ns" },
+ { "<a xmlns:p=\"ns\">p :t</a>", WS_E_INVALID_FORMAT, NULL, NULL, NULL },
+ { "<a xmlns:p=\"ns\">p: t</a>", S_OK, "p", " t", "ns" },
+ };
+
+ hr = WsReadQualifiedName( NULL, NULL, NULL, NULL, NULL, NULL );
+ ok( hr == E_INVALIDARG, "got %08x\n", hr );
+
+ hr = WsCreateReader( NULL, 0, &reader, NULL );
+ ok( hr == S_OK, "got %08x\n", hr );
+
+ hr = WsReadQualifiedName( reader, NULL, NULL, NULL, 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 = WsReadQualifiedName( reader, heap, NULL, NULL, NULL, NULL );
+ ok( hr == WS_E_INVALID_OPERATION, "got %08x\n", hr );
+
+ hr = set_input( reader, "<t/>", sizeof("<t/>") - 1 );
+ ok( hr == S_OK, "got %08x\n", hr );
+ hr = WsReadQualifiedName( reader, heap, NULL, NULL, NULL, NULL );
+ ok( hr == E_INVALIDARG, "got %08x\n", hr );
+
+ hr = set_input( reader, "<t/>", sizeof("<t/>") - 1 );
+ ok( hr == S_OK, "got %08x\n", hr );
+ hr = WsReadQualifiedName( reader, heap, NULL, &localname, NULL, NULL );
+ ok( hr == WS_E_INVALID_FORMAT, "got %08x\n", hr );
+
+ for (i = 0; i < sizeof(tests)/sizeof(tests[0]); i++)
+ {
+ hr = set_input( reader, tests[i].str, strlen(tests[i].str) );
+ ok( hr == S_OK, "%u: got %08x\n", i, hr );
+
+ hr = WsReadToStartElement( reader, NULL, NULL, &found, NULL );
+ ok( hr == S_OK, "%u: got %08x\n", i, hr );
+
+ hr = WsReadStartElement( reader, NULL );
+ ok( hr == S_OK, "%u: got %08x\n", i, hr );
+
+ prefix.length = localname.length = ns.length = 0xdeadbeef;
+ prefix.bytes = localname.bytes = ns.bytes = (BYTE *)0xdeadbeef;
+
+ hr = WsReadQualifiedName( reader, heap, &prefix, &localname, &ns, NULL );
+ ok( hr == tests[i].hr, "%u: got %08x\n", i, hr );
+ if (tests[i].hr == S_OK && hr == S_OK)
+ {
+ ok( prefix.length == strlen( tests[i].prefix ), "%u: got %u\n", i, prefix.length );
+ ok( !memcmp( prefix.bytes, tests[i].prefix, prefix.length ), "%u: wrong data\n", i );
+
+ ok( localname.length == strlen( tests[i].localname ), "%u: got %u\n", i, localname.length );
+ ok( !memcmp( localname.bytes, tests[i].localname, localname.length ), "%u: wrong data\n", i );
+
+ ok( ns.length == strlen( tests[i].ns ), "%u: got %u\n", i, ns.length );
+ ok( !memcmp( ns.bytes, tests[i].ns, ns.length ), "%u: wrong data\n", i );
+ }
+ else if (tests[i].hr != S_OK)
+ {
+ ok( prefix.length == 0xdeadbeef, "got %u\n", prefix.length );
+ ok( prefix.bytes == (BYTE *)0xdeadbeef, "got %p\n", prefix.bytes );
+
+ ok( localname.length == 0xdeadbeef, "got %u\n", localname.length );
+ ok( localname.bytes == (BYTE *)0xdeadbeef, "got %p\n", localname.bytes );
+
+ ok( ns.length == 0xdeadbeef, "got %u\n", ns.length );
+ ok( ns.bytes == (BYTE *)0xdeadbeef, "got %p\n", ns.bytes );
+ }
+ }
+
+ WsFreeHeap( heap );
+ WsFreeReader( reader );
+}
+
START_TEST(reader)
{
test_WsCreateError();
@@ -4279,4 +4390,5 @@ START_TEST(reader)
test_WsReadBytes();
test_WsReadChars();
test_WsReadCharsUtf8();
+ test_WsReadQualifiedName();
}
diff --git a/dlls/webservices/webservices.spec b/dlls/webservices/webservices.spec
index e63b805659..1ef8aaeb0f 100644
--- a/dlls/webservices/webservices.spec
+++ b/dlls/webservices/webservices.spec
@@ -117,7 +117,7 @@
@ stdcall WsReadMessageStart(ptr ptr ptr ptr)
@ stub WsReadMetadata
@ stdcall WsReadNode(ptr ptr)
-@ stub WsReadQualifiedName
+@ stdcall WsReadQualifiedName(ptr ptr ptr ptr ptr ptr)
@ stdcall WsReadStartAttribute(ptr long ptr)
@ stdcall WsReadStartElement(ptr ptr)
@ stdcall WsReadToStartElement(ptr ptr ptr ptr ptr)
diff --git a/include/webservices.h b/include/webservices.h
index a0857f6bc8..71b12ead49 100644
--- a/include/webservices.h
+++ b/include/webservices.h
@@ -1610,6 +1610,8 @@ HRESULT WINAPI WsReadEnvelopeStart(WS_MESSAGE*, WS_XML_READER*, WS_MESSAGE_DONE_
HRESULT WINAPI WsReadMessageEnd(WS_CHANNEL*, WS_MESSAGE*, const WS_ASYNC_CONTEXT*, WS_ERROR*);
HRESULT WINAPI WsReadMessageStart(WS_CHANNEL*, WS_MESSAGE*, const WS_ASYNC_CONTEXT*, WS_ERROR*);
HRESULT WINAPI WsReadNode(WS_XML_READER*, WS_ERROR*);
+HRESULT WINAPI WsReadQualifiedName(WS_XML_READER*, WS_HEAP*, WS_XML_STRING*, WS_XML_STRING*,
+ WS_XML_STRING*, WS_ERROR*);
HRESULT WINAPI WsReadStartAttribute(WS_XML_READER*, ULONG, WS_ERROR*);
HRESULT WINAPI WsReadStartElement(WS_XML_READER*, WS_ERROR*);
HRESULT WINAPI WsReadToStartElement(WS_XML_READER*, const WS_XML_STRING*, const WS_XML_STRING*,
--
2.11.0
More information about the wine-patches
mailing list