[3/6] webservices: Add initial support for binary XML in the writer.

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


Signed-off-by: Hans Leidekker <hans at codeweavers.com>
---
 dlls/webservices/tests/writer.c        |  46 ++++++++
 dlls/webservices/webservices_private.h | 188 +++++++++++++++++++++++++++++++++
 dlls/webservices/writer.c              | 182 ++++++++++++++++++++++++++++---
 3 files changed, 399 insertions(+), 17 deletions(-)

diff --git a/dlls/webservices/tests/writer.c b/dlls/webservices/tests/writer.c
index aa33b7633a..014266c5a5 100644
--- a/dlls/webservices/tests/writer.c
+++ b/dlls/webservices/tests/writer.c
@@ -3420,6 +3420,51 @@ static void test_WsWriteCharsUtf8(void)
     WsFreeWriter( writer );
 }
 
+static void test_binary_encoding(void)
+{
+    static const char res[] = {0x40,0x01,'t',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[] = "";
+    const WS_XML_STRING *prefix_ptr, *localname_ptr, *ns_ptr;
+    WS_XML_STRING str, str2, str3;
+    WS_XML_WRITER *writer;
+    HRESULT hr;
+    ULONG i;
+    static const struct
+    {
+        const char *prefix;
+        const char *localname;
+        const char *ns;
+        const char *result;
+    }
+    elem_tests[] =
+    {
+        { NULL, localname, empty, res },   /* short element */
+    };
+
+    hr = WsCreateWriter( NULL, 0, &writer, NULL );
+    ok( hr == S_OK, "got %08x\n", hr );
+
+    for (i = 0; i < sizeof(elem_tests)/sizeof(elem_tests[0]); i++)
+    {
+        hr = WsSetOutput( writer, &bin.encoding, &buf.output, NULL, 0, NULL );
+        ok( hr == S_OK, "%u: got %08x\n", i, hr );
+
+        prefix_ptr = init_xmlstring( elem_tests[i].prefix, &str );
+        localname_ptr = init_xmlstring( elem_tests[i].localname, &str2 );
+        ns_ptr = init_xmlstring( elem_tests[i].ns, &str3 );
+
+        hr = WsWriteStartElement( writer, prefix_ptr, localname_ptr, ns_ptr, NULL );
+        ok( hr == S_OK, "%u: got %08x\n", i, hr );
+        hr = WsWriteEndElement( writer, NULL );
+        ok( hr == S_OK, "%u: got %08x\n", i, hr );
+        if (hr == S_OK) check_output( writer, elem_tests[i].result, __LINE__ );
+    }
+
+    WsFreeWriter( writer );
+}
+
 START_TEST(writer)
 {
     test_WsCreateWriter();
@@ -3457,4 +3502,5 @@ START_TEST(writer)
     test_WsWriteBytes();
     test_WsWriteChars();
     test_WsWriteCharsUtf8();
+    test_binary_encoding();
 }
diff --git a/dlls/webservices/webservices_private.h b/dlls/webservices/webservices_private.h
index 75dfdb9fea..b1b2caa0eb 100644
--- a/dlls/webservices/webservices_private.h
+++ b/dlls/webservices/webservices_private.h
@@ -122,6 +122,194 @@ HRESULT channel_get_reader( WS_CHANNEL *, WS_XML_READER ** ) DECLSPEC_HIDDEN;
 
 HRESULT parse_url( const WS_STRING *, WS_URL_SCHEME_TYPE *, WCHAR **, USHORT * ) DECLSPEC_HIDDEN;
 
+enum record_type
+{
+    /* 0x00 reserved */
+    RECORD_ENDELEMENT                            = 0x01,
+    RECORD_COMMENT                               = 0x02,
+    RECORD_ARRAY                                 = 0x03,
+    RECORD_SHORT_ATTRIBUTE                       = 0x04,
+    RECORD_ATTRIBUTE                             = 0x05,
+    RECORD_SHORT_DICTIONARY_ATTRIBUTE            = 0x06,
+    RECORD_DICTIONARY_ATTRIBUTE                  = 0x07,
+    RECORD_SHORT_XMLNS_ATTRIBUTE                 = 0x08,
+    RECORD_XMLNS_ATTRIBUTE                       = 0x09,
+    RECORD_SHORT_DICTIONARY_XMLNS_ATTRIBUTE      = 0x0a,
+    RECORD_DICTIONARY_XMLNS_ATTRIBUTE            = 0x0b,
+    RECORD_PREFIX_DICTIONARY_ATTRIBUTE_A         = 0x0c,
+    RECORD_PREFIX_DICTIONARY_ATTRIBUTE_B         = 0x0d,
+    RECORD_PREFIX_DICTIONARY_ATTRIBUTE_C         = 0x0e,
+    RECORD_PREFIX_DICTIONARY_ATTRIBUTE_D         = 0x0f,
+    RECORD_PREFIX_DICTIONARY_ATTRIBUTE_E         = 0x10,
+    RECORD_PREFIX_DICTIONARY_ATTRIBUTE_F         = 0x11,
+    RECORD_PREFIX_DICTIONARY_ATTRIBUTE_G         = 0x12,
+    RECORD_PREFIX_DICTIONARY_ATTRIBUTE_H         = 0x13,
+    RECORD_PREFIX_DICTIONARY_ATTRIBUTE_I         = 0x14,
+    RECORD_PREFIX_DICTIONARY_ATTRIBUTE_J         = 0x15,
+    RECORD_PREFIX_DICTIONARY_ATTRIBUTE_K         = 0x16,
+    RECORD_PREFIX_DICTIONARY_ATTRIBUTE_L         = 0x17,
+    RECORD_PREFIX_DICTIONARY_ATTRIBUTE_M         = 0x18,
+    RECORD_PREFIX_DICTIONARY_ATTRIBUTE_N         = 0x19,
+    RECORD_PREFIX_DICTIONARY_ATTRIBUTE_O         = 0x1a,
+    RECORD_PREFIX_DICTIONARY_ATTRIBUTE_P         = 0x1b,
+    RECORD_PREFIX_DICTIONARY_ATTRIBUTE_Q         = 0x1c,
+    RECORD_PREFIX_DICTIONARY_ATTRIBUTE_R         = 0x1d,
+    RECORD_PREFIX_DICTIONARY_ATTRIBUTE_S         = 0x1e,
+    RECORD_PREFIX_DICTIONARY_ATTRIBUTE_T         = 0x1f,
+    RECORD_PREFIX_DICTIONARY_ATTRIBUTE_U         = 0x20,
+    RECORD_PREFIX_DICTIONARY_ATTRIBUTE_V         = 0x21,
+    RECORD_PREFIX_DICTIONARY_ATTRIBUTE_W         = 0x22,
+    RECORD_PREFIX_DICTIONARY_ATTRIBUTE_X         = 0x23,
+    RECORD_PREFIX_DICTIONARY_ATTRIBUTE_Y         = 0x24,
+    RECORD_PREFIX_DICTIONARY_ATTRIBUTE_Z         = 0x25,
+    RECORD_PREFIX_ATTRIBUTE_A                    = 0x26,
+    RECORD_PREFIX_ATTRIBUTE_B                    = 0x27,
+    RECORD_PREFIX_ATTRIBUTE_C                    = 0x28,
+    RECORD_PREFIX_ATTRIBUTE_D                    = 0x29,
+    RECORD_PREFIX_ATTRIBUTE_E                    = 0x2a,
+    RECORD_PREFIX_ATTRIBUTE_F                    = 0x2b,
+    RECORD_PREFIX_ATTRIBUTE_G                    = 0x2c,
+    RECORD_PREFIX_ATTRIBUTE_H                    = 0x2d,
+    RECORD_PREFIX_ATTRIBUTE_I                    = 0x2e,
+    RECORD_PREFIX_ATTRIBUTE_J                    = 0x2f,
+    RECORD_PREFIX_ATTRIBUTE_K                    = 0x30,
+    RECORD_PREFIX_ATTRIBUTE_L                    = 0x31,
+    RECORD_PREFIX_ATTRIBUTE_M                    = 0x32,
+    RECORD_PREFIX_ATTRIBUTE_N                    = 0x33,
+    RECORD_PREFIX_ATTRIBUTE_O                    = 0x34,
+    RECORD_PREFIX_ATTRIBUTE_P                    = 0x35,
+    RECORD_PREFIX_ATTRIBUTE_Q                    = 0x36,
+    RECORD_PREFIX_ATTRIBUTE_R                    = 0x37,
+    RECORD_PREFIX_ATTRIBUTE_S                    = 0x38,
+    RECORD_PREFIX_ATTRIBUTE_T                    = 0x39,
+    RECORD_PREFIX_ATTRIBUTE_U                    = 0x3a,
+    RECORD_PREFIX_ATTRIBUTE_V                    = 0x3b,
+    RECORD_PREFIX_ATTRIBUTE_W                    = 0x3c,
+    RECORD_PREFIX_ATTRIBUTE_X                    = 0x3d,
+    RECORD_PREFIX_ATTRIBUTE_Y                    = 0x3e,
+    RECORD_PREFIX_ATTRIBUTE_Z                    = 0x3f,
+    RECORD_SHORT_ELEMENT                         = 0x40,
+    RECORD_ELEMENT                               = 0x41,
+    RECORD_SHORT_DICTIONARY_ELEMENT              = 0x42,
+    RECORD_DICTIONARY_ELEMENT                    = 0x43,
+    RECORD_PREFIX_DICTIONARY_ELEMENT_A           = 0x44,
+    RECORD_PREFIX_DICTIONARY_ELEMENT_B           = 0x45,
+    RECORD_PREFIX_DICTIONARY_ELEMENT_C           = 0x46,
+    RECORD_PREFIX_DICTIONARY_ELEMENT_D           = 0x47,
+    RECORD_PREFIX_DICTIONARY_ELEMENT_E           = 0x48,
+    RECORD_PREFIX_DICTIONARY_ELEMENT_F           = 0x49,
+    RECORD_PREFIX_DICTIONARY_ELEMENT_G           = 0x4a,
+    RECORD_PREFIX_DICTIONARY_ELEMENT_H           = 0x4b,
+    RECORD_PREFIX_DICTIONARY_ELEMENT_I           = 0x4c,
+    RECORD_PREFIX_DICTIONARY_ELEMENT_J           = 0x4d,
+    RECORD_PREFIX_DICTIONARY_ELEMENT_K           = 0x4e,
+    RECORD_PREFIX_DICTIONARY_ELEMENT_L           = 0x4f,
+    RECORD_PREFIX_DICTIONARY_ELEMENT_M           = 0x50,
+    RECORD_PREFIX_DICTIONARY_ELEMENT_N           = 0x51,
+    RECORD_PREFIX_DICTIONARY_ELEMENT_O           = 0x52,
+    RECORD_PREFIX_DICTIONARY_ELEMENT_P           = 0x53,
+    RECORD_PREFIX_DICTIONARY_ELEMENT_Q           = 0x54,
+    RECORD_PREFIX_DICTIONARY_ELEMENT_R           = 0x55,
+    RECORD_PREFIX_DICTIONARY_ELEMENT_S           = 0x56,
+    RECORD_PREFIX_DICTIONARY_ELEMENT_T           = 0x57,
+    RECORD_PREFIX_DICTIONARY_ELEMENT_U           = 0x58,
+    RECORD_PREFIX_DICTIONARY_ELEMENT_V           = 0x59,
+    RECORD_PREFIX_DICTIONARY_ELEMENT_W           = 0x5a,
+    RECORD_PREFIX_DICTIONARY_ELEMENT_X           = 0x5b,
+    RECORD_PREFIX_DICTIONARY_ELEMENT_Y           = 0x5c,
+    RECORD_PREFIX_DICTIONARY_ELEMENT_Z           = 0x5d,
+    RECORD_PREFIX_ELEMENT_A                      = 0x5e,
+    RECORD_PREFIX_ELEMENT_B                      = 0x5f,
+    RECORD_PREFIX_ELEMENT_C                      = 0x60,
+    RECORD_PREFIX_ELEMENT_D                      = 0x61,
+    RECORD_PREFIX_ELEMENT_E                      = 0x62,
+    RECORD_PREFIX_ELEMENT_F                      = 0x63,
+    RECORD_PREFIX_ELEMENT_G                      = 0x64,
+    RECORD_PREFIX_ELEMENT_H                      = 0x65,
+    RECORD_PREFIX_ELEMENT_I                      = 0x66,
+    RECORD_PREFIX_ELEMENT_J                      = 0x67,
+    RECORD_PREFIX_ELEMENT_K                      = 0x68,
+    RECORD_PREFIX_ELEMENT_L                      = 0x69,
+    RECORD_PREFIX_ELEMENT_M                      = 0x6a,
+    RECORD_PREFIX_ELEMENT_N                      = 0x6b,
+    RECORD_PREFIX_ELEMENT_O                      = 0x6c,
+    RECORD_PREFIX_ELEMENT_P                      = 0x6d,
+    RECORD_PREFIX_ELEMENT_Q                      = 0x6e,
+    RECORD_PREFIX_ELEMENT_R                      = 0x6f,
+    RECORD_PREFIX_ELEMENT_S                      = 0x70,
+    RECORD_PREFIX_ELEMENT_T                      = 0x71,
+    RECORD_PREFIX_ELEMENT_U                      = 0x72,
+    RECORD_PREFIX_ELEMENT_V                      = 0x73,
+    RECORD_PREFIX_ELEMENT_W                      = 0x74,
+    RECORD_PREFIX_ELEMENT_X                      = 0x75,
+    RECORD_PREFIX_ELEMENT_Y                      = 0x76,
+    RECORD_PREFIX_ELEMENT_Z                      = 0x77,
+    /* 0x78 ... 0x7f reserved */
+    RECORD_ZERO_TEXT                             = 0x80,
+    RECORD_ZERO_TEXT_WITH_ENDELEMENT             = 0x81,
+    RECORD_ONE_TEXT                              = 0x82,
+    RECORD_ONE_TEXT_WITH_ENDELEMENT              = 0x83,
+    RECORD_FALSE_TEXT                            = 0x84,
+    RECORD_FALSE_TEXT_WITH_ENDELEMENT            = 0x85,
+    RECORD_TRUE_TEXT                             = 0x86,
+    RECORD_TRUE_TEXT_WITH_ENDELEMENT             = 0x87,
+    RECORD_INT8_TEXT                             = 0x88,
+    RECORD_INT8_TEXT_WITH_ENDELEMENT             = 0x89,
+    RECORD_INT16_TEXT                            = 0x8a,
+    RECORD_INT16_TEXT_WITH_ENDELEMENT            = 0x8b,
+    RECORD_INT32_TEXT                            = 0x8c,
+    RECORD_INT32_TEXT_WITH_ENDELEMENT            = 0x8d,
+    RECORD_INT64_TEXT                            = 0x8e,
+    RECORD_INT64_TEXT_WITH_ENDELEMENT            = 0x8f,
+    RECORD_FLOAT_TEXT                            = 0x90,
+    RECORD_FLOAT_TEXT_WITH_ENDELEMENT            = 0x91,
+    RECORD_DOUBLE_TEXT                           = 0x92,
+    RECORD_DOUBLE_TEXT_WITH_ENDELEMENT           = 0x93,
+    RECORD_DECIMAL_TEXT                          = 0x94,
+    RECORD_DECIMAL_TEXT_WITH_ENDELEMENT          = 0x95,
+    RECORD_DATETIME_TEXT                         = 0x96,
+    RECORD_DATETIME_TEXT_WITH_ENDELEMENT         = 0x97,
+    RECORD_CHARS8_TEXT                           = 0x98,
+    RECORD_CHARS8_TEXT_WITH_ENDELEMENT           = 0x99,
+    RECORD_CHARS16_TEXT                          = 0x9a,
+    RECORD_CHARS16_TEXT_WITH_ENDELEMENT          = 0x9b,
+    RECORD_CHARS32_TEXT                          = 0x9c,
+    RECORD_CHARS32_TEXT_WITH_ENDELEMENT          = 0x9d,
+    RECORD_BYTES8_TEXT                           = 0x9e,
+    RECORD_BYTES8_TEXT_WITH_ENDELEMENT           = 0x9f,
+    RECORD_BYTES16_TEXT                          = 0xa0,
+    RECORD_BYTES16_TEXT_WITH_ENDELEMENT          = 0xa1,
+    RECORD_BYTES32_TEXT                          = 0xa2,
+    RECORD_BYTES32_TEXT_WITH_ENDELEMENT          = 0xa3,
+    RECORD_STARTLIST_TEXT                        = 0xa4,
+    /* 0xa5 reserved */
+    RECORD_ENDLIST_TEXT                          = 0xa6,
+    /* 0xa7 reserved */
+    RECORD_EMPTY_TEXT                            = 0xa8,
+    RECORD_EMPTY_TEXT_WITH_ENDELEMENT            = 0xa9,
+    RECORD_DICTIONARY_TEXT                       = 0xaa,
+    RECORD_DICTIONARY_TEXT_WITH_ENDELEMENT       = 0xab,
+    RECORD_UNIQUEID_TEXT                         = 0xac,
+    RECORD_UNIQUEID_TEXT_WITH_ENDELEMENT         = 0xad,
+    RECORD_TIMESPAN_TEXT                         = 0xae,
+    RECORD_TIMESPAN_TEXT_WITH_ENDELEMENT         = 0xaf,
+    RECORD_UUID_TEXT                             = 0xb0,
+    RECORD_UUID_TEXT_WITH_ENDELEMENT             = 0xb1,
+    RECORD_UINT64_TEXT                           = 0xb2,
+    RECORD_UINT64_TEXT_WITH_ENDELEMENT           = 0xb3,
+    RECORD_BOOL_TEXT                             = 0xb4,
+    RECORD_BOOL_TEXT_WITH_ENDELEMENT             = 0xb5,
+    RECORD_UNICODE_CHARS8_TEXT                   = 0xb6,
+    RECORD_UNICODE_CHARS8_TEXT_WITH_ENDELEMENT   = 0xb7,
+    RECORD_UNICODE_CHARS16_TEXT                  = 0xb8,
+    RECORD_UNICODE_CHARS16_TEXT_WITH_ENDELEMENT  = 0xb9,
+    RECORD_UNICODE_CHARS32_TEXT                  = 0xba,
+    RECORD_UNICODE_CHARS32_TEXT_WITH_ENDELEMENT  = 0xbb,
+    RECORD_QNAME_DICTIONARY_TEXT                 = 0xbc,
+    RECORD_QNAME_DICTIONARY_TEXT_WITH_ENDELEMENT = 0xbd,
+    /* 0xbe ... 0xff reserved */
+};
+
 #define TICKS_PER_SEC       10000000
 #define TICKS_PER_MIN       (60 * (ULONGLONG)TICKS_PER_SEC)
 #define TICKS_PER_HOUR      (3600 * (ULONGLONG)TICKS_PER_SEC)
diff --git a/dlls/webservices/writer.c b/dlls/webservices/writer.c
index 2b5affc461..6b1994e059 100644
--- a/dlls/webservices/writer.c
+++ b/dlls/webservices/writer.c
@@ -71,19 +71,20 @@ enum writer_state
 
 struct writer
 {
-    ULONG                      magic;
-    CRITICAL_SECTION           cs;
-    ULONG                      write_pos;
-    unsigned char             *write_bufptr;
-    enum writer_state          state;
-    struct node               *root;
-    struct node               *current;
-    WS_XML_STRING             *current_ns;
-    WS_XML_WRITER_OUTPUT_TYPE  output_type;
-    struct xmlbuf             *output_buf;
-    WS_HEAP                   *output_heap;
-    ULONG                      prop_count;
-    struct prop                prop[sizeof(writer_props)/sizeof(writer_props[0])];
+    ULONG                        magic;
+    CRITICAL_SECTION             cs;
+    ULONG                        write_pos;
+    unsigned char               *write_bufptr;
+    enum writer_state            state;
+    struct node                 *root;
+    struct node                 *current;
+    WS_XML_STRING               *current_ns;
+    WS_XML_WRITER_ENCODING_TYPE  output_enc;
+    WS_XML_WRITER_OUTPUT_TYPE    output_type;
+    struct xmlbuf               *output_buf;
+    WS_HEAP                     *output_heap;
+    ULONG                        prop_count;
+    struct prop                  prop[sizeof(writer_props)/sizeof(writer_props[0])];
 };
 
 #define WRITER_MAGIC (('W' << 24) | ('R' << 16) | ('I' << 8) | 'T')
@@ -162,6 +163,7 @@ static HRESULT init_writer( struct writer *writer )
     if (!(node = alloc_node( WS_XML_NODE_TYPE_EOF ))) return E_OUTOFMEMORY;
     write_insert_eof( writer, node );
     writer->state        = WRITER_STATE_INITIAL;
+    writer->output_enc   = WS_XML_WRITER_ENCODING_TYPE_TEXT;
     return S_OK;
 }
 
@@ -372,6 +374,12 @@ HRESULT WINAPI WsSetOutput( WS_XML_WRITER *handle, const WS_XML_WRITER_ENCODING
             hr = E_NOTIMPL;
             goto done;
         }
+        writer->output_enc = WS_XML_WRITER_ENCODING_TYPE_TEXT;
+        break;
+    }
+    case WS_XML_WRITER_ENCODING_TYPE_BINARY:
+    {
+        writer->output_enc = WS_XML_WRITER_ENCODING_TYPE_BINARY;
         break;
     }
     default:
@@ -737,9 +745,9 @@ HRESULT WINAPI WsWriteEndAttribute( WS_XML_WRITER *handle, WS_ERROR *error )
     return S_OK;
 }
 
-static HRESULT write_startelement( struct writer *writer )
+static HRESULT write_startelement_text( struct writer *writer )
 {
-    WS_XML_ELEMENT_NODE *elem = &writer->current->hdr;
+    const WS_XML_ELEMENT_NODE *elem = &writer->current->hdr;
     ULONG size, i;
     HRESULT hr;
 
@@ -774,6 +782,114 @@ static HRESULT write_startelement( 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 )
+{
+    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_startelement_bin( struct writer *writer )
+{
+    const WS_XML_ELEMENT_NODE *elem = &writer->current->hdr;
+    enum record_type type = get_elem_record_type( elem );
+    HRESULT hr;
+
+    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 );
+    }
+
+    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 );
+
+    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 );
+
+    default:
+        FIXME( "unhandled record type %u\n", type );
+        return WS_E_NOT_SUPPORTED;
+    }
+}
+
+static HRESULT write_startelement( struct writer *writer )
+{
+    switch (writer->output_enc)
+    {
+    case WS_XML_WRITER_ENCODING_TYPE_TEXT:   return write_startelement_text( writer );
+    case WS_XML_WRITER_ENCODING_TYPE_BINARY: return write_startelement_bin( writer );
+    default:
+        ERR( "unhandled encoding %u\n", writer->output_enc );
+        return WS_E_NOT_SUPPORTED;
+    }
+}
+
 static struct node *write_find_startelement( struct writer *writer )
 {
     struct node *node;
@@ -790,7 +906,7 @@ static inline BOOL is_empty_element( const struct node *node )
     return node_type( head ) == WS_XML_NODE_TYPE_END_ELEMENT;
 }
 
-static HRESULT write_endelement( struct writer *writer, const WS_XML_ELEMENT_NODE *elem )
+static HRESULT write_endelement_text( struct writer *writer, const WS_XML_ELEMENT_NODE *elem )
 {
     ULONG size;
     HRESULT hr;
@@ -823,6 +939,26 @@ static HRESULT write_endelement( struct writer *writer, const WS_XML_ELEMENT_NOD
     return S_OK;
 }
 
+static HRESULT write_endelement_bin( struct writer *writer )
+{
+    HRESULT hr;
+    if ((hr = write_grow_buffer( writer, 1 )) != S_OK) return hr;
+    write_char( writer, RECORD_ENDELEMENT );
+    return S_OK;
+}
+
+static HRESULT write_endelement( struct writer *writer, const WS_XML_ELEMENT_NODE *elem )
+{
+    switch (writer->output_enc)
+    {
+    case WS_XML_WRITER_ENCODING_TYPE_TEXT:   return write_endelement_text( writer, elem );
+    case WS_XML_WRITER_ENCODING_TYPE_BINARY: return write_endelement_bin( writer );
+    default:
+        ERR( "unhandled encoding %u\n", writer->output_enc );
+        return WS_E_NOT_SUPPORTED;
+    }
+}
+
 static HRESULT write_close_element( struct writer *writer, struct node *node )
 {
     WS_XML_ELEMENT_NODE *elem = &node->hdr;
@@ -874,7 +1010,7 @@ HRESULT WINAPI WsWriteEndElement( WS_XML_WRITER *handle, WS_ERROR *error )
     return hr;
 }
 
-static HRESULT write_endstartelement( struct writer *writer )
+static HRESULT write_endstartelement_text( struct writer *writer )
 {
     HRESULT hr;
     if ((hr = write_grow_buffer( writer, 1 )) != S_OK) return hr;
@@ -882,6 +1018,18 @@ static HRESULT write_endstartelement( struct writer *writer )
     return S_OK;
 }
 
+static HRESULT write_endstartelement( struct writer *writer )
+{
+    switch (writer->output_enc)
+    {
+    case WS_XML_WRITER_ENCODING_TYPE_TEXT:   return write_endstartelement_text( writer );
+    case WS_XML_WRITER_ENCODING_TYPE_BINARY: return S_OK;
+    default:
+        ERR( "unhandled encoding %u\n", writer->output_enc );
+        return WS_E_NOT_SUPPORTED;
+    }
+}
+
 /**************************************************************************
  *          WsWriteEndStartElement		[webservices.@]
  */
-- 
2.11.0




More information about the wine-patches mailing list