[2/6] webservices: Add support for writing WS_XML_QNAME values.
Hans Leidekker
hans at codeweavers.com
Wed Jun 21 02:37:38 CDT 2017
Signed-off-by: Hans Leidekker <hans at codeweavers.com>
---
dlls/webservices/tests/writer.c | 22 +++++++-
dlls/webservices/writer.c | 120 +++++++++++++++++++++++++++++-----------
include/webservices.h | 19 +++++++
3 files changed, 128 insertions(+), 33 deletions(-)
diff --git a/dlls/webservices/tests/writer.c b/dlls/webservices/tests/writer.c
index 9cb6c7d..2d16cfc 100644
--- a/dlls/webservices/tests/writer.c
+++ b/dlls/webservices/tests/writer.c
@@ -2124,10 +2124,12 @@ static void test_WsCopyNode(void)
static void test_text_types(void)
{
static const WCHAR utf16W[] = {'u','t','f','1','6'};
- WS_XML_STRING localname = {1, (BYTE *)"t"}, ns = {0, NULL};
+ WS_XML_STRING prefix = {1, (BYTE *)"p"}, localname = {1, (BYTE *)"t"}, localname2 = {1, (BYTE *)"u"};
+ WS_XML_STRING ns = {0, NULL}, ns2 = {2, (BYTE *)"ns"};
WS_XML_WRITER *writer;
static const WS_XML_UTF8_TEXT val_utf8 = { {WS_XML_TEXT_TYPE_UTF8}, {4, (BYTE *)"utf8"} };
static WS_XML_UTF16_TEXT val_utf16 = { {WS_XML_TEXT_TYPE_UTF16} };
+ static WS_XML_QNAME_TEXT val_qname = { {WS_XML_TEXT_TYPE_QNAME} };
static const WS_XML_GUID_TEXT val_guid = { {WS_XML_TEXT_TYPE_GUID} };
static const WS_XML_UNIQUE_ID_TEXT val_urn = { {WS_XML_TEXT_TYPE_UNIQUE_ID} };
static const WS_XML_BOOL_TEXT val_bool = { {WS_XML_TEXT_TYPE_BOOL}, TRUE };
@@ -2155,12 +2157,15 @@ static void test_text_types(void)
{ &val_datetime.text, "<t>0001-01-01T00:00:00Z</t>" },
{ &val_double.text, "<t>1.1</t>" },
{ &val_base64.text, "<t>dGVzdA==</t>" },
+ { &val_qname.text, "<t>u</t>" },
};
HRESULT hr;
ULONG i;
val_utf16.bytes = (BYTE *)utf16W;
val_utf16.byteCount = sizeof(utf16W);
+ val_qname.localName = &localname2;
+ val_qname.ns = &ns;
hr = WsCreateWriter( NULL, 0, &writer, NULL );
ok( hr == S_OK, "got %08x\n", hr );
@@ -2180,6 +2185,21 @@ static void test_text_types(void)
check_output( writer, tests[i].result, __LINE__ );
}
+ hr = set_output( writer );
+ ok( hr == S_OK, "got %08x\n", hr );
+ hr = WsWriteStartElement( writer, &prefix, &localname, &ns2, NULL );
+ ok( hr == S_OK, "got %08x\n", hr );
+
+ val_qname.prefix = &prefix;
+ val_qname.localName = &localname2;
+ val_qname.ns = &ns2;
+ hr = WsWriteText( writer, &val_qname.text, NULL );
+ ok( hr == S_OK, "got %08x\n", hr );
+
+ hr = WsWriteEndElement( writer, NULL );
+ ok( hr == S_OK, "got %08x\n", hr );
+ check_output( writer, "<p:t xmlns:p=\"ns\">p:u</p:t>", __LINE__ );
+
WsFreeWriter( writer );
}
diff --git a/dlls/webservices/writer.c b/dlls/webservices/writer.c
index 9272b59..67ae1b7 100644
--- a/dlls/webservices/writer.c
+++ b/dlls/webservices/writer.c
@@ -1807,6 +1807,19 @@ ULONG format_urn( const GUID *ptr, unsigned char *buf )
ptr->Data4[4], ptr->Data4[5], ptr->Data4[6], ptr->Data4[7] );
}
+static ULONG format_qname( const WS_XML_STRING *prefix, const WS_XML_STRING *localname, unsigned char *buf )
+{
+ ULONG len = 0;
+ if (prefix && prefix->length)
+ {
+ memcpy( buf, prefix->bytes, prefix->length );
+ len += prefix->length;
+ buf[len++] = ':';
+ }
+ memcpy( buf + len, localname->bytes, localname->length );
+ return len + localname->length;
+}
+
static ULONG encode_base64( const unsigned char *bin, ULONG len, unsigned char *buf )
{
static const char base64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
@@ -1963,6 +1976,17 @@ static HRESULT text_to_utf8text( const WS_XML_TEXT *text, const WS_XML_UTF8_TEXT
(*ret)->value.length = format_datetime( &dt->value, (*ret)->value.bytes + len_old ) + len_old;
return S_OK;
}
+ case WS_XML_TEXT_TYPE_QNAME:
+ {
+ const WS_XML_QNAME_TEXT *qn = (const WS_XML_QNAME_TEXT *)text;
+ ULONG len = qn->localName->length;
+
+ if (qn->prefix && qn->prefix->length) len += qn->prefix->length + 1;
+ if (!(*ret = alloc_utf8_text( NULL, len_old + len ))) return E_OUTOFMEMORY;
+ if (old) memcpy( (*ret)->value.bytes, old->value.bytes, len_old );
+ (*ret)->value.length = format_qname( qn->prefix, qn->localName, (*ret)->value.bytes + len_old ) + len_old;
+ return S_OK;
+ }
default:
FIXME( "unhandled text type %u\n", text->textType );
return E_NOTIMPL;
@@ -2752,6 +2776,53 @@ static HRESULT write_type_xml_string( struct writer *writer, WS_TYPE_MAPPING map
return write_type_text( writer, mapping, &utf8.text );
}
+static HRESULT find_prefix( struct writer *writer, const WS_XML_STRING *ns, const WS_XML_STRING **prefix )
+{
+ const struct node *node;
+ for (node = writer->current; 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]->ns, ns, NULL ) != S_OK) continue;
+ *prefix = elem->attributes[i]->prefix;
+ return S_OK;
+ }
+ }
+ return WS_E_INVALID_FORMAT;
+}
+
+static HRESULT write_type_qname( struct writer *writer, WS_TYPE_MAPPING mapping,
+ const WS_XML_QNAME_DESCRIPTION *desc, WS_WRITE_OPTION option,
+ const void *value, ULONG size )
+{
+ WS_XML_QNAME_TEXT qname;
+ const WS_XML_QNAME *ptr;
+ const WS_XML_STRING *prefix;
+ HRESULT hr;
+
+ if (desc)
+ {
+ FIXME( "description not supported\n" );
+ return E_NOTIMPL;
+ }
+
+ if (!option) return E_INVALIDARG;
+ if ((hr = get_value_ptr( option, value, size, sizeof(*ptr), (const void **)&ptr )) != S_OK) return hr;
+ if (option == WS_WRITE_NILLABLE_POINTER && !ptr) return write_add_nil_attribute( writer );
+ if (option == WS_WRITE_NILLABLE_VALUE && is_nil_value( value, size )) return write_add_nil_attribute( writer );
+
+ if (((hr = find_prefix( writer, &ptr->ns, &prefix )) != S_OK)) return hr;
+
+ qname.text.textType = WS_XML_TEXT_TYPE_QNAME;
+ qname.prefix = (WS_XML_STRING *)prefix;
+ qname.localName = (WS_XML_STRING *)&ptr->localName;
+ qname.ns = (WS_XML_STRING *)&ptr->ns;
+ return write_type_text( writer, mapping, &qname.text );
+}
+
static WS_WRITE_OPTION get_field_write_option( WS_TYPE type, ULONG options )
{
if (options & WS_FIELD_POINTER)
@@ -2778,6 +2849,7 @@ static WS_WRITE_OPTION get_field_write_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_WRITE_NILLABLE_VALUE;
@@ -3006,6 +3078,9 @@ static HRESULT write_type( struct writer *writer, WS_TYPE_MAPPING mapping, WS_TY
case WS_XML_STRING_TYPE:
return write_type_xml_string( writer, mapping, desc, option, value, size );
+ case WS_XML_QNAME_TYPE:
+ return write_type_qname( writer, mapping, desc, option, value, size );
+
case WS_STRUCT_TYPE:
return write_type_struct( writer, mapping, desc, option, value, size );
@@ -3400,37 +3475,21 @@ HRESULT WINAPI WsWriteXmlnsAttribute( WS_XML_WRITER *handle, const WS_XML_STRING
return hr;
}
-static HRESULT find_prefix( struct writer *writer, const WS_XML_STRING *ns, const WS_XML_STRING **prefix )
-{
- const struct node *node;
- for (node = writer->current; 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]->ns, ns, NULL ) != S_OK) continue;
- *prefix = elem->attributes[i]->prefix;
- return S_OK;
- }
- }
- return WS_E_INVALID_FORMAT;
-}
-
static HRESULT write_qualified_name( struct writer *writer, const WS_XML_STRING *prefix,
- const WS_XML_STRING *localname )
+ const WS_XML_STRING *localname, const WS_XML_STRING *ns )
{
+ WS_XML_QNAME_TEXT qname = {{WS_XML_TEXT_TYPE_QNAME}};
HRESULT hr;
- if (prefix->length)
- {
- if ((hr = write_grow_buffer( writer, prefix->length + localname->length + 1 )) != S_OK) return hr;
- write_bytes( writer, prefix->bytes, prefix->length );
- write_char( writer, ':' );
- }
- else if ((hr = write_grow_buffer( writer, localname->length )) != S_OK) return hr;
- write_bytes( writer, localname->bytes, localname->length );
- return S_OK;
+
+ if ((hr = write_flush( writer )) != S_OK) return hr;
+ if (!prefix && ((hr = find_prefix( writer, ns, &prefix )) != S_OK)) return hr;
+
+ qname.prefix = (WS_XML_STRING *)prefix;
+ qname.localName = (WS_XML_STRING *)localname;
+ qname.ns = (WS_XML_STRING *)ns;
+
+ if ((hr = write_add_text_node( writer, &qname.text )) != S_OK) return hr;
+ return write_text( writer, ((const WS_XML_TEXT_NODE *)writer->current)->text, 0 );
}
/**************************************************************************
@@ -3475,11 +3534,8 @@ HRESULT WINAPI WsWriteQualifiedName( WS_XML_WRITER *handle, const WS_XML_STRING
return E_INVALIDARG;
}
- if ((hr = write_flush( writer )) != S_OK) goto done;
- if (!prefix && ((hr = find_prefix( writer, ns, &prefix )) != S_OK)) goto done;
- hr = write_qualified_name( writer, prefix, localname );
+ hr = write_qualified_name( writer, prefix, localname, ns );
-done:
LeaveCriticalSection( &writer->cs );
return hr;
}
diff --git a/include/webservices.h b/include/webservices.h
index 84fa206..bea4ade 100644
--- a/include/webservices.h
+++ b/include/webservices.h
@@ -423,6 +423,13 @@ typedef struct _WS_XML_STRING_DESCRIPTION {
ULONG maxByteCount;
} WS_XML_STRING_DESCRIPTION;
+typedef struct _WS_XML_QNAME_DESCRIPTION {
+ ULONG minLocalNameByteCount;
+ ULONG maxLocalNameByteCount;
+ ULONG minNsByteCount;
+ ULONG maxNsByteCount;
+} WS_XML_QNAME_DESCRIPTION;
+
struct _WS_ENUM_VALUE {
int value;
WS_XML_STRING *name;
@@ -647,6 +654,13 @@ typedef struct _WS_XML_UNIQUE_ID_TEXT {
GUID value;
} WS_XML_UNIQUE_ID_TEXT;
+typedef struct _WS_XML_QNAME_TEXT {
+ WS_XML_TEXT text;
+ WS_XML_STRING *prefix;
+ WS_XML_STRING *localName;
+ WS_XML_STRING *ns;
+} WS_XML_QNAME_TEXT;
+
typedef enum {
WS_BOOL_VALUE_TYPE,
WS_INT8_VALUE_TYPE,
@@ -700,6 +714,11 @@ typedef struct _WS_XML_NODE_POSITION {
void *node;
} WS_XML_NODE_POSITION;
+typedef struct _WS_XML_QNAME {
+ WS_XML_STRING localName;
+ WS_XML_STRING ns;
+} WS_XML_QNAME;
+
typedef enum {
WS_SERVICE_PROXY_STATE_CREATED,
WS_SERVICE_PROXY_STATE_OPENING,
--
2.1.4
More information about the wine-patches
mailing list