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