Hans Leidekker : webservices: Add support for reading attributes in binary mode.
Alexandre Julliard
julliard at winehq.org
Thu May 25 14:42:15 CDT 2017
Module: wine
Branch: master
Commit: 78428d963eb742eae5c35010640d673aa94f7cf6
URL: http://source.winehq.org/git/wine.git/?a=commit;h=78428d963eb742eae5c35010640d673aa94f7cf6
Author: Hans Leidekker <hans at codeweavers.com>
Date: Thu May 25 12:54:41 2017 +0200
webservices: Add support for reading attributes in binary mode.
Signed-off-by: Hans Leidekker <hans at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>
---
dlls/webservices/reader.c | 141 ++++++++++++++++++++++++++++++++++++++++
dlls/webservices/tests/reader.c | 69 ++++++++++++++++++++
2 files changed, 210 insertions(+)
diff --git a/dlls/webservices/reader.c b/dlls/webservices/reader.c
index 39f0202..a5e3efc 100644
--- a/dlls/webservices/reader.c
+++ b/dlls/webservices/reader.c
@@ -1221,6 +1221,11 @@ error:
return hr;
}
+static inline BOOL is_text_type( unsigned char type )
+{
+ return (type >= RECORD_ZERO_TEXT && type <= RECORD_QNAME_DICTIONARY_TEXT_WITH_ENDELEMENT);
+}
+
static HRESULT read_int31( struct reader *reader, ULONG *len )
{
unsigned char byte;
@@ -1258,6 +1263,42 @@ static HRESULT read_string( struct reader *reader, WS_XML_STRING **str )
return hr;
}
+static HRESULT read_attribute_value_bin( struct reader *reader, WS_XML_ATTRIBUTE *attr )
+{
+ WS_XML_UTF8_TEXT *utf8 = NULL;
+ unsigned char type;
+ HRESULT hr;
+ ULONG len;
+
+ if ((hr = read_byte( reader, &type )) != S_OK) return hr;
+ if (!is_text_type( type )) return WS_E_INVALID_FORMAT;
+
+ switch (type)
+ {
+ case RECORD_CHARS8_TEXT:
+ {
+ unsigned char len8;
+ if ((hr = read_byte( reader, &len8 )) != S_OK) return hr;
+ len = len8;
+ break;
+ }
+ default:
+ ERR( "unhandled record type %02x\n", type );
+ return WS_E_NOT_SUPPORTED;
+ }
+
+ if (!(utf8 = alloc_utf8_text( NULL, len ))) return E_OUTOFMEMORY;
+ if (!len) utf8->value.bytes = (BYTE *)(utf8 + 1); /* quirk */
+ if ((hr = read_bytes( reader, utf8->value.bytes, len )) != S_OK)
+ {
+ heap_free( utf8 );
+ return hr;
+ }
+
+ attr->value = &utf8->text;
+ return S_OK;
+}
+
static HRESULT read_attribute_text( struct reader *reader, WS_XML_ATTRIBUTE **ret )
{
static const WS_XML_STRING xmlns = {5, (BYTE *)"xmlns"};
@@ -1314,6 +1355,83 @@ error:
return hr;
}
+static inline BOOL is_attribute_type( unsigned char type )
+{
+ return (type >= RECORD_SHORT_ATTRIBUTE && type <= RECORD_PREFIX_ATTRIBUTE_Z);
+}
+
+static HRESULT read_attribute_bin( struct reader *reader, WS_XML_ATTRIBUTE **ret )
+{
+ WS_XML_ATTRIBUTE *attr;
+ unsigned char type = 0;
+ HRESULT hr;
+
+ if ((hr = read_byte( reader, &type )) != S_OK) return hr;
+ if (!is_attribute_type( type )) return WS_E_INVALID_FORMAT;
+ if (!(attr = heap_alloc_zero( sizeof(*attr) ))) return E_OUTOFMEMORY;
+
+ if (type >= RECORD_PREFIX_ATTRIBUTE_A && type <= RECORD_PREFIX_ATTRIBUTE_Z)
+ {
+ unsigned char ch = type - RECORD_PREFIX_ATTRIBUTE_A + 'a';
+ if (!(attr->prefix = alloc_xml_string( &ch, 1 )))
+ {
+ hr = E_OUTOFMEMORY;
+ goto error;
+ }
+ if ((hr = read_string( reader, &attr->localName )) != S_OK) goto error;
+ if ((hr = read_attribute_value_bin( reader, attr )) != S_OK) goto error;
+ }
+ else
+ {
+ switch (type)
+ {
+ case RECORD_SHORT_ATTRIBUTE:
+ if (!(attr->prefix = alloc_xml_string( NULL, 0 )))
+ {
+ hr = E_OUTOFMEMORY;
+ goto error;
+ }
+ if ((hr = read_string( reader, &attr->localName )) != S_OK) goto error;
+ if ((hr = read_attribute_value_bin( reader, attr )) != S_OK) goto error;
+ break;
+
+ case RECORD_ATTRIBUTE:
+ if ((hr = read_string( reader, &attr->prefix )) != S_OK) goto error;
+ if ((hr = read_string( reader, &attr->localName )) != S_OK) goto error;
+ if ((hr = read_attribute_value_bin( reader, attr )) != S_OK) goto error;
+ break;
+
+ case RECORD_SHORT_XMLNS_ATTRIBUTE:
+ if (!(attr->prefix = alloc_xml_string( NULL, 0 )))
+ {
+ hr = E_OUTOFMEMORY;
+ goto error;
+ }
+ if ((hr = read_string( reader, &attr->ns )) != S_OK) goto error;
+ attr->isXmlNs = 1;
+ break;
+
+ case RECORD_XMLNS_ATTRIBUTE:
+ if ((hr = read_string( reader, &attr->prefix )) != S_OK) goto error;
+ if ((hr = read_string( reader, &attr->ns )) != S_OK) goto error;
+ if ((hr = bind_prefix( reader, attr->prefix, attr->ns )) != S_OK) goto error;
+ attr->isXmlNs = 1;
+ break;
+
+ default:
+ ERR( "unhandled record type %02x\n", type );
+ return WS_E_NOT_SUPPORTED;
+ }
+ }
+
+ *ret = attr;
+ return S_OK;
+
+error:
+ free_attribute( attr );
+ return hr;
+}
+
static inline struct node *find_parent( struct reader *reader )
{
if (node_type( reader->current ) == WS_XML_NODE_TYPE_END_ELEMENT)
@@ -1438,6 +1556,28 @@ static inline BOOL is_element_type( unsigned char type )
return (type >= RECORD_SHORT_ELEMENT && type <= RECORD_PREFIX_ELEMENT_Z);
}
+static HRESULT read_attributes_bin( struct reader *reader, WS_XML_ELEMENT_NODE *elem )
+{
+ WS_XML_ATTRIBUTE *attr;
+ unsigned char type;
+ HRESULT hr;
+
+ reader->current_attr = 0;
+ for (;;)
+ {
+ if ((hr = read_peek( reader, &type )) != S_OK) return hr;
+ if (!is_attribute_type( type )) break;
+ if ((hr = read_attribute_bin( reader, &attr )) != S_OK) return hr;
+ if ((hr = append_attribute( elem, attr )) != S_OK)
+ {
+ free_attribute( attr );
+ return hr;
+ }
+ reader->current_attr++;
+ }
+ return S_OK;
+}
+
static HRESULT read_element_bin( struct reader *reader )
{
struct node *node = NULL, *parent;
@@ -1491,6 +1631,7 @@ static HRESULT read_element_bin( struct reader *reader )
goto error;
}
+ if ((hr = read_attributes_bin( reader, elem )) != S_OK) goto error;
if ((hr = set_namespaces( reader, elem )) != S_OK) goto error;
read_insert_node( reader, parent, node );
diff --git a/dlls/webservices/tests/reader.c b/dlls/webservices/tests/reader.c
index 34fe2da..41cbadc 100644
--- a/dlls/webservices/tests/reader.c
+++ b/dlls/webservices/tests/reader.c
@@ -4510,8 +4510,13 @@ static void test_binary_encoding(void)
{
static const char res[] =
{0x40,0x01,'t',0x01};
+ static const char res2[] =
+ {0x6d,0x01,'t',0x09,0x01,'p',0x02,'n','s',0x01};
+ static const char res3[] =
+ {0x41,0x02,'p','2',0x01,'t',0x09,0x02,'p','2',0x02,'n','s',0x01};
const WS_XML_NODE *node;
const WS_XML_ELEMENT_NODE *elem;
+ const WS_XML_ATTRIBUTE *attr;
WS_XML_READER *reader;
HRESULT hr;
@@ -4543,6 +4548,70 @@ static void test_binary_encoding(void)
ok( hr == S_OK, "got %08x\n", hr );
ok( node->nodeType == WS_XML_NODE_TYPE_END_ELEMENT, "got %u\n", node->nodeType );
+ /* single character prefix element */
+ hr = set_input_bin( reader, res2, sizeof(res2) );
+ ok( hr == S_OK, "got %08x\n", hr );
+
+ hr = WsReadNode( reader, NULL );
+ ok( hr == S_OK, "got %08x\n", hr );
+ hr = WsGetReaderNode( reader, &node, NULL );
+ ok( hr == S_OK, "got %08x\n", hr );
+ ok( node->nodeType == WS_XML_NODE_TYPE_ELEMENT, "got %u\n", node->nodeType );
+ elem = (const WS_XML_ELEMENT_NODE *)node;
+ ok( elem->prefix->length == 1, "got %u\n", elem->prefix->length );
+ ok( !memcmp( elem->prefix->bytes, "p", 1 ), "wrong prefix\n" );
+ ok( elem->localName->length == 1, "got %u\n", elem->localName->length );
+ ok( !memcmp( elem->localName->bytes, "t", 1 ), "wrong name\n" );
+ ok( elem->ns->length == 2, "got %u\n", elem->ns->length );
+ ok( !memcmp( elem->ns->bytes, "ns", 2 ), "wrong namespace\n" );
+ ok( elem->attributeCount == 1, "got %u\n", elem->attributeCount );
+ ok( !elem->isEmpty, "empty\n" );
+ attr = elem->attributes[0];
+ ok( !attr->singleQuote, "single quote\n" );
+ ok( attr->isXmlNs, "not xmlns\n" );
+ ok( attr->prefix->length == 1, "got %u\n", attr->prefix->length );
+ ok( !memcmp( attr->prefix->bytes, "p", 1 ), "wrong prefix\n" );
+ ok( attr->ns->length == 2, "got %u\n", attr->ns->length );
+ ok( !memcmp( attr->ns->bytes, "ns", 2 ), "wrong namespace\n" );
+
+ hr = WsReadNode( reader, NULL );
+ ok( hr == S_OK, "got %08x\n", hr );
+ hr = WsGetReaderNode( reader, &node, NULL );
+ ok( hr == S_OK, "got %08x\n", hr );
+ ok( node->nodeType == WS_XML_NODE_TYPE_END_ELEMENT, "got %u\n", node->nodeType );
+
+ /* element */
+ hr = set_input_bin( reader, res3, sizeof(res3) );
+ ok( hr == S_OK, "got %08x\n", hr );
+
+ hr = WsReadNode( reader, NULL );
+ ok( hr == S_OK, "got %08x\n", hr );
+ hr = WsGetReaderNode( reader, &node, NULL );
+ ok( hr == S_OK, "got %08x\n", hr );
+ ok( node->nodeType == WS_XML_NODE_TYPE_ELEMENT, "got %u\n", node->nodeType );
+ elem = (const WS_XML_ELEMENT_NODE *)node;
+ ok( elem->prefix->length == 2, "got %u\n", elem->prefix->length );
+ ok( !memcmp( elem->prefix->bytes, "p2", 2 ), "wrong prefix\n" );
+ ok( elem->localName->length == 1, "got %u\n", elem->localName->length );
+ ok( !memcmp( elem->localName->bytes, "t", 1 ), "wrong name\n" );
+ ok( elem->ns->length == 2, "got %u\n", elem->ns->length );
+ ok( !memcmp( elem->ns->bytes, "ns", 2 ), "wrong namespace\n" );
+ ok( elem->attributeCount == 1, "got %u\n", elem->attributeCount );
+ ok( !elem->isEmpty, "empty\n" );
+ attr = elem->attributes[0];
+ ok( !attr->singleQuote, "single quote\n" );
+ ok( attr->isXmlNs, "not xmlns\n" );
+ ok( attr->prefix->length == 2, "got %u\n", attr->prefix->length );
+ ok( !memcmp( attr->prefix->bytes, "p2", 2 ), "wrong prefix\n" );
+ ok( attr->ns->length == 2, "got %u\n", attr->ns->length );
+ ok( !memcmp( attr->ns->bytes, "ns", 2 ), "wrong namespace\n" );
+
+ hr = WsReadNode( reader, NULL );
+ ok( hr == S_OK, "got %08x\n", hr );
+ hr = WsGetReaderNode( reader, &node, NULL );
+ ok( hr == S_OK, "got %08x\n", hr );
+ ok( node->nodeType == WS_XML_NODE_TYPE_END_ELEMENT, "got %u\n", node->nodeType );
+
WsFreeReader( reader );
}
More information about the wine-cvs
mailing list