[4/6] webservices: Add support for writing namespace attributes in binary mode.

Hans Leidekker hans at codeweavers.com
Tue May 23 05:03:52 CDT 2017


Signed-off-by: Hans Leidekker <hans at codeweavers.com>
---
 dlls/webservices/tests/writer.c |   7 +-
 dlls/webservices/writer.c       | 214 +++++++++++++++++++++++++---------------
 2 files changed, 139 insertions(+), 82 deletions(-)

diff --git a/dlls/webservices/tests/writer.c b/dlls/webservices/tests/writer.c
index 014266c5a5..7fd2d4432b 100644
--- a/dlls/webservices/tests/writer.c
+++ b/dlls/webservices/tests/writer.c
@@ -3423,9 +3423,12 @@ static void test_WsWriteCharsUtf8(void)
 static void test_binary_encoding(void)
 {
     static const char res[] = {0x40,0x01,'t',0x01,0};
+    static const char res2[] = {0x6d,0x01,'t',0x09,0x01,'p',0x02,'n','s',0x01,0};
+    static const char res3[] = {0x41,0x02,'p','2',0x01,'t',0x09,0x02,'p','2',0x02,'n','s',0x01,0};
     WS_XML_WRITER_BINARY_ENCODING bin = {{WS_XML_WRITER_ENCODING_TYPE_BINARY}};
     WS_XML_WRITER_BUFFER_OUTPUT buf = {{WS_XML_WRITER_OUTPUT_TYPE_BUFFER}};
-    static const char localname[] = "t", empty[] = "";
+    static const char prefix[] = "p", prefix2[] = "p2";
+    static const char localname[] = "t", empty[] = "", ns[] = "ns";
     const WS_XML_STRING *prefix_ptr, *localname_ptr, *ns_ptr;
     WS_XML_STRING str, str2, str3;
     WS_XML_WRITER *writer;
@@ -3441,6 +3444,8 @@ static void test_binary_encoding(void)
     elem_tests[] =
     {
         { NULL, localname, empty, res },   /* short element */
+        { prefix, localname, ns, res2 },   /* one character prefix element */
+        { prefix2, localname, ns, res3 },  /* element */
     };
 
     hr = WsCreateWriter( NULL, 0, &writer, NULL );
diff --git a/dlls/webservices/writer.c b/dlls/webservices/writer.c
index 6b1994e059..a2b0763bb2 100644
--- a/dlls/webservices/writer.c
+++ b/dlls/webservices/writer.c
@@ -624,7 +624,7 @@ static HRESULT set_current_namespace( struct writer *writer, const WS_XML_STRING
     return S_OK;
 }
 
-static HRESULT write_namespace_attribute( struct writer *writer, WS_XML_ATTRIBUTE *attr )
+static HRESULT write_namespace_attribute_text( struct writer *writer, const WS_XML_ATTRIBUTE *attr )
 {
     unsigned char quote = attr->singleQuote ? '\'' : '"';
     ULONG size;
@@ -650,6 +650,103 @@ static HRESULT write_namespace_attribute( struct writer *writer, WS_XML_ATTRIBUT
     return S_OK;
 }
 
+static enum record_type get_xmlns_record_type( const WS_XML_ATTRIBUTE *attr )
+{
+    if (!attr->prefix || !attr->prefix->length) return RECORD_SHORT_XMLNS_ATTRIBUTE;
+    return RECORD_XMLNS_ATTRIBUTE;
+};
+
+static HRESULT write_int31( struct writer *writer, ULONG len )
+{
+    HRESULT hr;
+
+    if ((hr = write_grow_buffer( writer, 1 )) != S_OK) return hr;
+    if (len < 0x80)
+    {
+        write_char( writer, len );
+        return S_OK;
+    }
+    write_char( writer, (len & 0x7f) | 0x80 );
+
+    if ((hr = write_grow_buffer( writer, 1 )) != S_OK) return hr;
+    if ((len >>= 7) < 0x80)
+    {
+        write_char( writer, len );
+        return S_OK;
+    }
+    write_char( writer, (len & 0x7f) | 0x80 );
+
+    if ((hr = write_grow_buffer( writer, 1 )) != S_OK) return hr;
+    if ((len >>= 7) < 0x80)
+    {
+        write_char( writer, len );
+        return S_OK;
+    }
+    write_char( writer, (len & 0x7f) | 0x80 );
+
+    if ((hr = write_grow_buffer( writer, 1 )) != S_OK) return hr;
+    if ((len >>= 7) < 0x80)
+    {
+        write_char( writer, len );
+        return S_OK;
+    }
+    write_char( writer, (len & 0x7f) | 0x80 );
+
+    if ((hr = write_grow_buffer( writer, 1 )) != S_OK) return hr;
+    if ((len >>= 7) < 0x08)
+    {
+        write_char( writer, len );
+        return S_OK;
+    }
+    return WS_E_INVALID_FORMAT;
+}
+
+static HRESULT write_string( struct writer *writer, const BYTE *bytes, ULONG len )
+{
+    HRESULT hr;
+    if ((hr = write_int31( writer, len )) != S_OK) return hr;
+    if ((hr = write_grow_buffer( writer, len )) != S_OK) return hr;
+    write_bytes( writer, bytes, len );
+    return S_OK;
+}
+
+static HRESULT write_namespace_attribute_bin( struct writer *writer, const WS_XML_ATTRIBUTE *attr )
+{
+    enum record_type type = get_xmlns_record_type( attr );
+    HRESULT hr;
+
+    if ((hr = write_grow_buffer( writer, 1 )) != S_OK) return hr;
+    write_char( writer, type );
+
+    switch (type)
+    {
+    case RECORD_SHORT_XMLNS_ATTRIBUTE:
+        break;
+
+    case RECORD_XMLNS_ATTRIBUTE:
+        if ((hr = write_string( writer, attr->prefix->bytes, attr->prefix->length )) != S_OK) return hr;
+        break;
+
+    default:
+        ERR( "unhandled record type %u\n", type );
+        return WS_E_NOT_SUPPORTED;
+    }
+
+    return write_string( writer, attr->ns->bytes, attr->ns->length );
+}
+
+static HRESULT write_namespace_attribute( struct writer *writer, const WS_XML_ATTRIBUTE *attr )
+{
+    switch (writer->output_enc)
+    {
+    case WS_XML_WRITER_ENCODING_TYPE_TEXT:   return write_namespace_attribute_text( writer, attr );
+    case WS_XML_WRITER_ENCODING_TYPE_BINARY: return write_namespace_attribute_bin( writer, attr );
+    default:
+        ERR( "unhandled encoding %u\n", writer->output_enc );
+        return WS_E_NOT_SUPPORTED;
+    }
+}
+
 static HRESULT write_add_namespace_attribute( struct writer *writer, const WS_XML_STRING *prefix,
                                               const WS_XML_STRING *ns, BOOL single )
 {
@@ -745,25 +842,10 @@ HRESULT WINAPI WsWriteEndAttribute( WS_XML_WRITER *handle, WS_ERROR *error )
     return S_OK;
 }
 
-static HRESULT write_startelement_text( struct writer *writer )
+static HRESULT write_attributes( struct writer *writer, const WS_XML_ELEMENT_NODE *elem )
 {
-    const WS_XML_ELEMENT_NODE *elem = &writer->current->hdr;
-    ULONG size, i;
+    ULONG i;
     HRESULT hr;
-
-    /* '<prefix:localname prefix:attr="value"... xmlns:prefix="ns"'... */
-
-    size = elem->localName->length + 1 /* '<' */;
-    if (elem->prefix && elem->prefix->length) size += elem->prefix->length + 1 /* ':' */;
-    if ((hr = write_grow_buffer( writer, size )) != S_OK) return hr;
-
-    write_char( writer, '<' );
-    if (elem->prefix && elem->prefix->length)
-    {
-        write_bytes( writer, elem->prefix->bytes, elem->prefix->length );
-        write_char( writer, ':' );
-    }
-    write_bytes( writer, elem->localName->bytes, elem->localName->length );
     for (i = 0; i < elem->attributeCount; i++)
     {
         if (elem->attributes[i]->isXmlNs) continue;
@@ -782,69 +864,37 @@ static HRESULT write_startelement_text( struct writer *writer )
     return S_OK;
 }
 
-static enum record_type get_elem_record_type( const WS_XML_ELEMENT_NODE *elem )
-{
-    if (!elem->prefix || !elem->prefix->length) return RECORD_SHORT_ELEMENT;
-    if (elem->prefix->length == 1 && elem->prefix->bytes[0] >= 'a' && elem->prefix->bytes[0] <= 'z')
-    {
-        return RECORD_PREFIX_ELEMENT_A + elem->prefix->bytes[0] - 'a';
-    }
-    return RECORD_ELEMENT;
-};
-
-static HRESULT write_int31( struct writer *writer, ULONG len )
+static HRESULT write_startelement_text( struct writer *writer )
 {
+    const WS_XML_ELEMENT_NODE *elem = &writer->current->hdr;
+    ULONG size;
     HRESULT hr;
 
-    if ((hr = write_grow_buffer( writer, 1 )) != S_OK) return hr;
-    if (len < 0x80)
-    {
-        write_char( writer, len );
-        return S_OK;
-    }
-    write_char( writer, (len & 0x7f) | 0x80 );
-
-    if ((hr = write_grow_buffer( writer, 1 )) != S_OK) return hr;
-    if ((len >>= 7) < 0x80)
-    {
-        write_char( writer, len );
-        return S_OK;
-    }
-    write_char( writer, (len & 0x7f) | 0x80 );
-
-    if ((hr = write_grow_buffer( writer, 1 )) != S_OK) return hr;
-    if ((len >>= 7) < 0x80)
-    {
-        write_char( writer, len );
-        return S_OK;
-    }
-    write_char( writer, (len & 0x7f) | 0x80 );
+    /* '<prefix:localname prefix:attr="value"... xmlns:prefix="ns"'... */
 
-    if ((hr = write_grow_buffer( writer, 1 )) != S_OK) return hr;
-    if ((len >>= 7) < 0x80)
-    {
-        write_char( writer, len );
-        return S_OK;
-    }
-    write_char( writer, (len & 0x7f) | 0x80 );
+    size = elem->localName->length + 1 /* '<' */;
+    if (elem->prefix && elem->prefix->length) size += elem->prefix->length + 1 /* ':' */;
+    if ((hr = write_grow_buffer( writer, size )) != S_OK) return hr;
 
-    if ((hr = write_grow_buffer( writer, 1 )) != S_OK) return hr;
-    if ((len >>= 7) < 0x08)
+    write_char( writer, '<' );
+    if (elem->prefix && elem->prefix->length)
     {
-        write_char( writer, len );
-        return S_OK;
+        write_bytes( writer, elem->prefix->bytes, elem->prefix->length );
+        write_char( writer, ':' );
     }
-    return WS_E_INVALID_FORMAT;
+    write_bytes( writer, elem->localName->bytes, elem->localName->length );
+    return write_attributes( writer, elem );
 }
 
-static HRESULT write_string( struct writer *writer, const BYTE *bytes, ULONG len )
+static enum record_type get_elem_record_type( const WS_XML_ELEMENT_NODE *elem )
 {
-    HRESULT hr;
-    if ((hr = write_int31( writer, len )) != S_OK) return hr;
-    if ((hr = write_grow_buffer( writer, len )) != S_OK) return hr;
-    write_bytes( writer, bytes, len );
-    return S_OK;
-}
+    if (!elem->prefix || !elem->prefix->length) return RECORD_SHORT_ELEMENT;
+    if (elem->prefix->length == 1 && elem->prefix->bytes[0] >= 'a' && elem->prefix->bytes[0] <= 'z')
+    {
+        return RECORD_PREFIX_ELEMENT_A + elem->prefix->bytes[0] - 'a';
+    }
+    return RECORD_ELEMENT;
+};
 
 static HRESULT write_startelement_bin( struct writer *writer )
 {
@@ -852,30 +902,32 @@ static HRESULT write_startelement_bin( struct writer *writer )
     enum record_type type = get_elem_record_type( elem );
     HRESULT hr;
 
+    if ((hr = write_grow_buffer( writer, 1 )) != S_OK) return hr;
+    write_char( writer, type );
+
     if (type >= RECORD_PREFIX_ELEMENT_A && type <= RECORD_PREFIX_ELEMENT_Z)
     {
-        if ((hr = write_grow_buffer( writer, 1 )) != S_OK) return hr;
-        write_char( writer, type );
-        return write_string( writer, elem->localName->bytes, elem->localName->length );
+        if ((hr = write_string( writer, elem->localName->bytes, elem->localName->length )) != S_OK) return hr;
+        return write_attributes( writer, elem );
     }
 
     switch (type)
     {
     case RECORD_SHORT_ELEMENT:
-        if ((hr = write_grow_buffer( writer, 1 )) != S_OK) return hr;
-        write_char( writer, type );
-        return write_string( writer, elem->localName->bytes, elem->localName->length );
+        if ((hr = write_string( writer, elem->localName->bytes, elem->localName->length )) != S_OK) return hr;
+        break;
 
     case RECORD_ELEMENT:
-        if ((hr = write_grow_buffer( writer, 1 )) != S_OK) return hr;
-        write_char( writer, type );
         if ((hr = write_string( writer, elem->prefix->bytes, elem->prefix->length )) != S_OK) return hr;
-        return write_string( writer, elem->localName->bytes, elem->localName->length );
+        if ((hr = write_string( writer, elem->localName->bytes, elem->localName->length )) != S_OK) return hr;
+        break;
 
     default:
-        FIXME( "unhandled record type %u\n", type );
+        ERR( "unhandled record type %u\n", type );
         return WS_E_NOT_SUPPORTED;
     }
+
+    return write_attributes( writer, elem );
 }
 
 static HRESULT write_startelement( struct writer *writer )
-- 
2.11.0




More information about the wine-patches mailing list