[2/4] webservices: Add support for dictionary strings in the reader.

Hans Leidekker hans at codeweavers.com
Tue May 30 03:09:06 CDT 2017


Signed-off-by: Hans Leidekker <hans at codeweavers.com>
---
 dlls/webservices/reader.c       |  88 ++++++++++-
 dlls/webservices/tests/reader.c | 314 ++++++++++++++++++++++++++++++++++++++--
 2 files changed, 389 insertions(+), 13 deletions(-)

diff --git a/dlls/webservices/reader.c b/dlls/webservices/reader.c
index 6dd6de4..8485ad6 100644
--- a/dlls/webservices/reader.c
+++ b/dlls/webservices/reader.c
@@ -376,6 +376,7 @@ struct reader
     const unsigned char         *input_data;
     ULONG                        input_size;
     ULONG                        text_conv_offset;
+    WS_XML_DICTIONARY           *dict;
     ULONG                        prop_count;
     struct prop                  prop[sizeof(reader_props)/sizeof(reader_props[0])];
 };
@@ -521,6 +522,7 @@ static HRESULT init_reader( struct reader *reader )
     if (!(node = alloc_node( WS_XML_NODE_TYPE_EOF ))) return E_OUTOFMEMORY;
     read_insert_eof( reader, node );
     reader->input_enc    = WS_XML_READER_ENCODING_TYPE_TEXT;
+    reader->dict         = NULL;
     return S_OK;
 }
 
@@ -1277,6 +1279,17 @@ static HRESULT read_string( struct reader *reader, WS_XML_STRING **str )
     return hr;
 }
 
+static HRESULT read_dict_string( struct reader *reader, WS_XML_STRING **str )
+{
+    ULONG id;
+    HRESULT hr;
+    if ((hr = read_int31( reader, &id )) != S_OK) return hr;
+    if (!reader->dict || (id >>= 1) >= reader->dict->stringCount) return WS_E_INVALID_FORMAT;
+    if (!(*str = alloc_xml_string( NULL, 0 ))) return E_OUTOFMEMORY;
+    *(*str) = reader->dict->strings[id];
+    return S_OK;
+}
+
 static HRESULT read_attribute_value_bin( struct reader *reader, WS_XML_ATTRIBUTE *attr )
 {
     WS_XML_UTF8_TEXT *utf8 = NULL;
@@ -1395,6 +1408,17 @@ static HRESULT read_attribute_bin( struct reader *reader, WS_XML_ATTRIBUTE **ret
         if ((hr = read_string( reader, &attr->localName )) != S_OK) goto error;
         if ((hr = read_attribute_value_bin( reader, attr )) != S_OK) goto error;
     }
+    else if (type >= RECORD_PREFIX_DICTIONARY_ATTRIBUTE_A && type <= RECORD_PREFIX_DICTIONARY_ATTRIBUTE_Z)
+    {
+        unsigned char ch = type - RECORD_PREFIX_DICTIONARY_ATTRIBUTE_A + 'a';
+        if (!(attr->prefix = alloc_xml_string( &ch, 1 )))
+        {
+            hr = E_OUTOFMEMORY;
+            goto error;
+        }
+        if ((hr = read_dict_string( reader, &attr->localName )) != S_OK) goto error;
+        if ((hr = read_attribute_value_bin( reader, attr )) != S_OK) goto error;
+    }
     else
     {
         switch (type)
@@ -1415,6 +1439,22 @@ static HRESULT read_attribute_bin( struct reader *reader, WS_XML_ATTRIBUTE **ret
             if ((hr = read_attribute_value_bin( reader, attr )) != S_OK) goto error;
             break;
 
+        case RECORD_SHORT_DICTIONARY_ATTRIBUTE:
+            if (!(attr->prefix = alloc_xml_string( NULL, 0 )))
+            {
+                hr = E_OUTOFMEMORY;
+                goto error;
+            }
+            if ((hr = read_dict_string( reader, &attr->localName )) != S_OK) goto error;
+            if ((hr = read_attribute_value_bin( reader, attr )) != S_OK) goto error;
+            break;
+
+        case RECORD_DICTIONARY_ATTRIBUTE:
+            if ((hr = read_string( reader, &attr->prefix )) != S_OK) goto error;
+            if ((hr = read_dict_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 )))
             {
@@ -1422,6 +1462,7 @@ static HRESULT read_attribute_bin( struct reader *reader, WS_XML_ATTRIBUTE **ret
                 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;
 
@@ -1432,6 +1473,24 @@ static HRESULT read_attribute_bin( struct reader *reader, WS_XML_ATTRIBUTE **ret
             attr->isXmlNs = 1;
             break;
 
+        case RECORD_SHORT_DICTIONARY_XMLNS_ATTRIBUTE:
+            if (!(attr->prefix = alloc_xml_string( NULL, 0 )))
+            {
+                hr = E_OUTOFMEMORY;
+                goto error;
+            }
+            if ((hr = read_dict_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;
+
+        case RECORD_DICTIONARY_XMLNS_ATTRIBUTE:
+            if ((hr = read_string( reader, &attr->prefix )) != S_OK) goto error;
+            if ((hr = read_dict_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;
@@ -1615,6 +1674,16 @@ static HRESULT read_element_bin( struct reader *reader )
         }
         if ((hr = read_string( reader, &elem->localName )) != S_OK) goto error;
     }
+    else if (type >= RECORD_PREFIX_DICTIONARY_ELEMENT_A && type <= RECORD_PREFIX_DICTIONARY_ELEMENT_Z)
+    {
+        unsigned char ch = type - RECORD_PREFIX_DICTIONARY_ELEMENT_A + 'a';
+        if (!(elem->prefix = alloc_xml_string( &ch, 1 )))
+        {
+            hr = E_OUTOFMEMORY;
+            goto error;
+        }
+        if ((hr = read_dict_string( reader, &elem->localName )) != S_OK) goto error;
+    }
     else
     {
         switch (type)
@@ -1633,6 +1702,20 @@ static HRESULT read_element_bin( struct reader *reader )
             if ((hr = read_string( reader, &elem->localName )) != S_OK) goto error;
             break;
 
+        case RECORD_SHORT_DICTIONARY_ELEMENT:
+            if (!(elem->prefix = alloc_xml_string( NULL, 0 )))
+            {
+                hr = E_OUTOFMEMORY;
+                goto error;
+            }
+            if ((hr = read_dict_string( reader, &elem->localName )) != S_OK) goto error;
+            break;
+
+        case RECORD_DICTIONARY_ELEMENT:
+            if ((hr = read_string( reader, &elem->prefix )) != S_OK) goto error;
+            if ((hr = read_dict_string( reader, &elem->localName )) != S_OK) goto error;
+            break;
+
         default:
             ERR( "unhandled record type %02x\n", type );
             return WS_E_NOT_SUPPORTED;
@@ -5180,9 +5263,12 @@ HRESULT WINAPI WsSetInput( WS_XML_READER *handle, const WS_XML_READER_ENCODING *
         break;
     }
     case WS_XML_READER_ENCODING_TYPE_BINARY:
+    {
+        WS_XML_READER_BINARY_ENCODING *bin = (WS_XML_READER_BINARY_ENCODING *)encoding;
         reader->input_enc = WS_XML_READER_ENCODING_TYPE_BINARY;
+        reader->dict      = bin->staticDictionary;
         break;
-
+    }
     default:
         FIXME( "encoding type %u not supported\n", encoding->encodingType );
         hr = E_NOTIMPL;
diff --git a/dlls/webservices/tests/reader.c b/dlls/webservices/tests/reader.c
index 8f31ea5..7eab4b8 100644
--- a/dlls/webservices/tests/reader.c
+++ b/dlls/webservices/tests/reader.c
@@ -18,6 +18,7 @@
 
 #include <stdio.h>
 #include "windows.h"
+#include "rpc.h"
 #include "webservices.h"
 #include "wine/test.h"
 
@@ -4495,9 +4496,9 @@ static void test_WsSkipNode(void)
     WsFreeReader( reader );
 }
 
-static HRESULT set_input_bin( WS_XML_READER *reader, const char *data, ULONG size )
+static HRESULT set_input_bin( WS_XML_READER *reader, const char *data, ULONG size, WS_XML_DICTIONARY *dict )
 {
-    WS_XML_READER_BINARY_ENCODING bin = {{WS_XML_READER_ENCODING_TYPE_BINARY}};
+    WS_XML_READER_BINARY_ENCODING bin = {{WS_XML_READER_ENCODING_TYPE_BINARY}, dict};
     WS_XML_READER_BUFFER_INPUT buf;
 
     buf.input.inputType = WS_XML_READER_INPUT_TYPE_BUFFER;
@@ -4540,7 +4541,7 @@ static void test_binary_encoding(void)
     ok( hr == S_OK, "got %08x\n", hr );
 
     /* short element */
-    hr = set_input_bin( reader, res, sizeof(res) );
+    hr = set_input_bin( reader, res, sizeof(res), NULL );
     ok( hr == S_OK, "got %08x\n", hr );
 
     hr = WsReadNode( reader, NULL );
@@ -4553,6 +4554,7 @@ static void test_binary_encoding(void)
     ok( elem->prefix->bytes == NULL, "bytes set\n" );
     ok( elem->localName->length == 1, "got %u\n", elem->localName->length );
     ok( !memcmp( elem->localName->bytes, "t", 1 ), "wrong name\n" );
+    todo_wine ok( elem->localName->dictionary != NULL, "dictionary not set\n" );
     ok( !elem->ns->length, "got %u\n", elem->ns->length );
     ok( elem->ns->bytes != NULL, "bytes not set\n" );
     ok( !elem->attributeCount, "got %u\n", elem->attributeCount );
@@ -4565,7 +4567,7 @@ static void test_binary_encoding(void)
     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) );
+    hr = set_input_bin( reader, res2, sizeof(res2), NULL );
     ok( hr == S_OK, "got %08x\n", hr );
 
     hr = WsReadNode( reader, NULL );
@@ -4597,7 +4599,7 @@ static void test_binary_encoding(void)
     ok( node->nodeType == WS_XML_NODE_TYPE_END_ELEMENT, "got %u\n", node->nodeType );
 
     /* element */
-    hr = set_input_bin( reader, res3, sizeof(res3) );
+    hr = set_input_bin( reader, res3, sizeof(res3), NULL );
     ok( hr == S_OK, "got %08x\n", hr );
 
     hr = WsReadNode( reader, NULL );
@@ -4629,7 +4631,7 @@ static void test_binary_encoding(void)
     ok( node->nodeType == WS_XML_NODE_TYPE_END_ELEMENT, "got %u\n", node->nodeType );
 
     /* element with text */
-    hr = set_input_bin( reader, res4, sizeof(res4) );
+    hr = set_input_bin( reader, res4, sizeof(res4), NULL );
     ok( hr == S_OK, "got %08x\n", hr );
 
     hr = WsReadNode( reader, NULL );
@@ -4672,7 +4674,7 @@ static void test_binary_encoding(void)
     ok( node->nodeType == WS_XML_NODE_TYPE_END_ELEMENT, "got %u\n", node->nodeType );
 
     /* short attribute */
-    hr = set_input_bin( reader, res100, sizeof(res100) );
+    hr = set_input_bin( reader, res100, sizeof(res100), NULL );
     ok( hr == S_OK, "got %08x\n", hr );
 
     hr = WsReadNode( reader, NULL );
@@ -4709,7 +4711,7 @@ static void test_binary_encoding(void)
     ok( node->nodeType == WS_XML_NODE_TYPE_END_ELEMENT, "got %u\n", node->nodeType );
 
     /* single character prefix attribute */
-    hr = set_input_bin( reader, res101, sizeof(res101) );
+    hr = set_input_bin( reader, res101, sizeof(res101), NULL );
     ok( hr == S_OK, "got %08x\n", hr );
 
     hr = WsReadNode( reader, NULL );
@@ -4754,7 +4756,7 @@ static void test_binary_encoding(void)
     ok( node->nodeType == WS_XML_NODE_TYPE_END_ELEMENT, "got %u\n", node->nodeType );
 
     /* attribute */
-    hr = set_input_bin( reader, res102, sizeof(res102) );
+    hr = set_input_bin( reader, res102, sizeof(res102), NULL );
     ok( hr == S_OK, "got %08x\n", hr );
 
     hr = WsReadNode( reader, NULL );
@@ -4799,7 +4801,7 @@ static void test_binary_encoding(void)
     ok( node->nodeType == WS_XML_NODE_TYPE_END_ELEMENT, "got %u\n", node->nodeType );
 
     /* attribute with value */
-    hr = set_input_bin( reader, res103, sizeof(res103) );
+    hr = set_input_bin( reader, res103, sizeof(res103), NULL );
     ok( hr == S_OK, "got %08x\n", hr );
 
     hr = WsReadNode( reader, NULL );
@@ -4850,7 +4852,7 @@ static void test_binary_encoding(void)
     ok( node->nodeType == WS_XML_NODE_TYPE_EOF, "got %u\n", node->nodeType );
 
     /* comment */
-    hr = set_input_bin( reader, res200, sizeof(res200) );
+    hr = set_input_bin( reader, res200, sizeof(res200), NULL );
     ok( hr == S_OK, "got %08x\n", hr );
 
     hr = WsReadNode( reader, NULL );
@@ -4862,7 +4864,7 @@ static void test_binary_encoding(void)
     ok( comment->value.length == 7, "got %u\n", comment->value.length );
     ok( !memcmp( comment->value.bytes, "comment", 7 ), "wrong data\n" );
 
-    hr = set_input_bin( reader, res, sizeof(res) );
+    hr = set_input_bin( reader, res, sizeof(res), NULL );
     ok( hr == S_OK, "got %08x\n", hr );
 
     found = -1;
@@ -4877,6 +4879,293 @@ static void test_binary_encoding(void)
     WsFreeReader( reader );
 }
 
+static void test_dictionary(void)
+{
+    static const char res[] =
+        {0x42,0x04,0x01};
+    static const char res2[] =
+        {0x53,0x06,0x0b,0x01,'p',0x0a,0x01};
+    static const char res3[] =
+        {0x43,0x02,'p','2',0x06,0x0b,0x02,'p','2',0x0a,0x01};
+    static const char res4[] =
+        {0x42,0x06,0x06,0x06,0x98,0x00,0x01};
+    static const char res5[] =
+        {0x42,0x06,0x1b,0x06,0x98,0x00,0x0b,0x01,'p',0x0a,0x01};
+    static const char res6[] =
+        {0x42,0x06,0x07,0x02,'p','2',0x06,0x98,0x00,0x0b,0x02,'p','2',0x0a,0x01};
+    const WS_XML_NODE *node;
+    const WS_XML_ELEMENT_NODE *elem;
+    const WS_XML_ATTRIBUTE *attr;
+    const WS_XML_UTF8_TEXT *utf8;
+    WS_XML_STRING strings[6];
+    WS_XML_DICTIONARY dict;
+    WS_XML_READER *reader;
+    HRESULT hr;
+
+    hr = WsCreateReader( NULL, 0, &reader, NULL );
+    ok( hr == S_OK, "got %08x\n", hr );
+
+    strings[0].length     = 0;
+    strings[0].bytes      = NULL;
+    strings[0].dictionary = &dict;
+    strings[0].id         = 0;
+    strings[1].length     = 1;
+    strings[1].bytes      = (BYTE *)"p";
+    strings[1].dictionary = &dict;
+    strings[1].id         = 1;
+    strings[2].length     = 1;
+    strings[2].bytes      = (BYTE *)"t";
+    strings[2].dictionary = &dict;
+    strings[2].id         = ~0u;
+    strings[3].length     = 1;
+    strings[3].bytes      = (BYTE *)"u";
+    strings[3].dictionary = &dict;
+    strings[3].id         = 3;
+    strings[4].length     = 2;
+    strings[4].bytes      = (BYTE *)"p2";
+    strings[4].dictionary = &dict;
+    strings[4].id         = 4;
+    strings[5].length     = 2;
+    strings[5].bytes      = (BYTE *)"ns";
+    strings[5].dictionary = &dict;
+    strings[5].id         = 5;
+
+    UuidCreate( &dict.guid );
+    dict.strings     = strings;
+    dict.stringCount = sizeof(strings)/sizeof(strings[0]);
+    dict.isConst     = TRUE;
+
+    /* short dictionary element */
+    hr = set_input_bin( reader, res, sizeof(res), &dict );
+    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, "got %u\n", elem->prefix->length );
+    ok( elem->prefix->bytes == NULL, "bytes set\n" );
+    ok( elem->localName->length == 1, "got %u\n", elem->localName->length );
+    ok( !memcmp( elem->localName->bytes, "t", 1 ), "wrong name\n" );
+    ok( elem->localName->dictionary == &dict, "unexpected dict\n" );
+    ok( elem->localName->id == ~0u, "unexpected id %08x\n", elem->localName->id );
+    ok( !elem->ns->length, "got %u\n", elem->ns->length );
+    ok( elem->ns->bytes != NULL, "bytes not set\n" );
+    ok( !elem->attributeCount, "got %u\n", elem->attributeCount );
+    ok( !elem->isEmpty, "empty\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 );
+
+    /* single character prefix dictionary element */
+    hr = set_input_bin( reader, res2, sizeof(res2), &dict );
+    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, "u", 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" );
+    ok( attr->ns->dictionary == &dict, "unexpected dict\n" );
+    ok( attr->ns->id == 5, "unexpected id %08x\n", attr->ns->id );
+
+    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 );
+
+    /* dictionary element */
+    hr = set_input_bin( reader, res3, sizeof(res3), &dict );
+    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, "u", 1 ), "wrong name\n" );
+    ok( elem->localName->dictionary == &dict, "unexpected dict\n" );
+    ok( elem->localName->id == 3, "unexpected id %08x\n", elem->localName->id );
+    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 );
+
+    /* short dictionary attribute */
+    hr = set_input_bin( reader, res4, sizeof(res4), &dict );
+    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, "got %u\n", elem->prefix->length );
+    ok( elem->localName->length == 1, "got %u\n", elem->localName->length );
+    ok( !memcmp( elem->localName->bytes, "u", 1 ), "wrong name\n" );
+    ok( !elem->ns->length, "got %u\n", elem->ns->length );
+    ok( elem->ns->bytes != NULL, "bytes not set\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, "is xmlns\n" );
+    ok( !attr->prefix->length, "got %u\n", attr->prefix->length );
+    ok( attr->localName->length == 1, "got %u\n", attr->localName->length );
+    ok( attr->localName->dictionary == &dict, "unexpected dict\n" );
+    ok( attr->localName->id == 3, "unexpected id %08x\n", attr->localName->id );
+    ok( !memcmp( attr->localName->bytes, "u", 1 ), "wrong name\n" );
+    ok( !attr->ns->length, "got %u\n", attr->ns->length );
+    ok( elem->ns->bytes != NULL, "bytes not set\n" );
+    ok( attr->value != NULL, "value not set\n" );
+    utf8 = (const WS_XML_UTF8_TEXT *)attr->value;
+    ok( utf8->text.textType == WS_XML_TEXT_TYPE_UTF8, "got %u\n", utf8->text.textType );
+    ok( !utf8->value.length, "got %u\n", utf8->value.length );
+    ok( utf8->value.bytes != NULL, "bytes not set\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 );
+
+    /* single character prefix dictionary attribute */
+    hr = set_input_bin( reader, res5, sizeof(res5), &dict );
+    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, "got %u\n", elem->prefix->length );
+    ok( elem->localName->length == 1, "got %u\n", elem->localName->length );
+    ok( !memcmp( elem->localName->bytes, "u", 1 ), "wrong name\n" );
+    ok( !elem->ns->length, "got %u\n", elem->ns->length );
+    ok( elem->ns->bytes != NULL, "ns not set\n" );
+    ok( elem->attributeCount == 2, "got %u\n", elem->attributeCount );
+    ok( !elem->isEmpty, "empty\n" );
+    attr = elem->attributes[0];
+    ok( !attr->singleQuote, "single quote\n" );
+    ok( !attr->isXmlNs, "is 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->localName->length == 1, "got %u\n", attr->localName->length );
+    ok( !memcmp( attr->localName->bytes, "u", 1 ), "wrong name\n" );
+    ok( attr->localName->dictionary == &dict, "unexpected dict\n" );
+    ok( attr->localName->id == 3, "unexpected id %08x\n", attr->localName->id );
+    ok( attr->ns->length == 2, "got %u\n", attr->ns->length );
+    ok( !memcmp( attr->ns->bytes, "ns", 2 ), "wrong namespace\n" );
+    ok( attr->value != NULL, "value not set\n" );
+    utf8 = (const WS_XML_UTF8_TEXT *)attr->value;
+    ok( utf8->text.textType == WS_XML_TEXT_TYPE_UTF8, "got %u\n", utf8->text.textType );
+    ok( !utf8->value.length, "got %u\n", utf8->value.length );
+    ok( utf8->value.bytes != NULL, "bytes not set\n" );
+    attr = elem->attributes[1];
+    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 );
+
+    /* dictionary attribute */
+    hr = set_input_bin( reader, res6, sizeof(res6), &dict );
+    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, "got %u\n", elem->prefix->length );
+    ok( elem->localName->length == 1, "got %u\n", elem->localName->length );
+    ok( !memcmp( elem->localName->bytes, "u", 1 ), "wrong name\n" );
+    ok( !elem->ns->length, "got %u\n", elem->ns->length );
+    ok( elem->ns->bytes != NULL, "ns not set\n" );
+    ok( elem->attributeCount == 2, "got %u\n", elem->attributeCount );
+    ok( !elem->isEmpty, "empty\n" );
+    attr = elem->attributes[0];
+    ok( !attr->singleQuote, "single quote\n" );
+    ok( !attr->isXmlNs, "is 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->localName->length == 1, "got %u\n", attr->localName->length );
+    ok( !memcmp( attr->localName->bytes, "u", 1 ), "wrong name\n" );
+    ok( attr->localName->dictionary == &dict, "unexpected dict\n" );
+    ok( attr->localName->id == 3, "unexpected id %08x\n", attr->localName->id );
+    ok( attr->ns->length == 2, "got %u\n", attr->ns->length );
+    ok( !memcmp( attr->ns->bytes, "ns", 2 ), "wrong namespace\n" );
+    ok( attr->value != NULL, "value not set\n" );
+    utf8 = (const WS_XML_UTF8_TEXT *)attr->value;
+    ok( utf8->text.textType == WS_XML_TEXT_TYPE_UTF8, "got %u\n", utf8->text.textType );
+    ok( !utf8->value.length, "got %u\n", utf8->value.length );
+    ok( utf8->value.bytes != NULL, "bytes not set\n" );
+    attr = elem->attributes[1];
+    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 );
+}
+
 START_TEST(reader)
 {
     test_WsCreateError();
@@ -4920,4 +5209,5 @@ START_TEST(reader)
     test_WsReadAttribute();
     test_WsSkipNode();
     test_binary_encoding();
+    test_dictionary();
 }
-- 
2.1.4




More information about the wine-patches mailing list