[2/2] webservices: Add support for dynamic string callbacks.
Hans Leidekker
hans at codeweavers.com
Thu Jun 22 03:43:11 CDT 2017
Signed-off-by: Hans Leidekker <hans at codeweavers.com>
---
dlls/webservices/tests/writer.c | 81 ++++++++++++++++++++++++++++++++++++++++-
dlls/webservices/writer.c | 55 ++++++++++++++++++++--------
2 files changed, 118 insertions(+), 18 deletions(-)
diff --git a/dlls/webservices/tests/writer.c b/dlls/webservices/tests/writer.c
index 2d16cfc..cf8ab61 100644
--- a/dlls/webservices/tests/writer.c
+++ b/dlls/webservices/tests/writer.c
@@ -3649,6 +3649,34 @@ static const WS_XML_STRING *init_xmlstring_dict( WS_XML_DICTIONARY *dict, ULONG
return str;
}
+static HRESULT CALLBACK dict_cb( void *state, const WS_XML_STRING *str, BOOL *found, ULONG *id, WS_ERROR *error )
+{
+ ULONG *call_count = state;
+
+ (*call_count)++;
+ switch (str->bytes[0])
+ {
+ case 't':
+ *id = 1;
+ *found = TRUE;
+ break;
+
+ case 'n':
+ *id = 2;
+ *found = TRUE;
+ break;
+
+ case 'v':
+ *found = FALSE;
+ return WS_E_OTHER;
+
+ default:
+ *found = FALSE;
+ break;
+ }
+ return S_OK;
+}
+
static void test_dictionary(void)
{
static const char res[] =
@@ -3659,6 +3687,12 @@ static void test_dictionary(void)
{0x53,0x06,0x0b,0x01,'p',0x0a,0x01};
static const char res4[] =
{0x43,0x02,'p','2',0x06,0x0b,0x02,'p','2',0x0a,0x01};
+ static const char res5[] =
+ {0x42,0x03,0x0a,0x05,0x01};
+ static const char res6[] =
+ {0x40,0x01,0x75,0x0a,0x05,0x01};
+ static const char res7[] =
+ {0x40,0x01,0x76,0x0a,0x05,0x01};
static const char res100[] =
{0x42,0x06,0x06,0x06,0x98,0x00,0x01};
static const char res101[] =
@@ -3672,7 +3706,7 @@ static void test_dictionary(void)
WS_XML_DICTIONARY dict;
WS_XML_WRITER *writer;
HRESULT hr;
- ULONG i;
+ ULONG i, call_count;
static const struct
{
ULONG prefix;
@@ -3768,12 +3802,55 @@ static void test_dictionary(void)
hr = WsWriteStartAttribute( writer, prefix_ptr, localname_ptr, ns_ptr, FALSE, NULL );
ok( hr == S_OK, "%u: got %08x\n", i, hr );
hr = WsWriteEndAttribute( writer, NULL );
- ok( hr == S_OK, "got %08x\n", hr );
+ 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_bin( writer, attr_tests[i].result, attr_tests[i].len_result, __LINE__ );
}
+ /* callback */
+ bin.staticDictionary = NULL;
+ bin.dynamicStringCallback = dict_cb;
+ bin.dynamicStringCallbackState = &call_count;
+
+ hr = WsSetOutput( writer, &bin.encoding, &buf.output, NULL, 0, NULL );
+ ok( hr == S_OK, "got %08x\n", hr );
+ init_xmlstring( "t", &localname );
+ init_xmlstring( "ns", &ns );
+ call_count = 0;
+ hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
+ ok( hr == S_OK, "got %08x\n", hr );
+ hr = WsWriteEndElement( writer, NULL );
+ ok( hr == S_OK, "got %08x\n", hr );
+ ok( call_count == 2, "got %u\n", call_count );
+ check_output_bin( writer, res5, sizeof(res5), __LINE__ );
+
+ /* unknown string */
+ hr = WsSetOutput( writer, &bin.encoding, &buf.output, NULL, 0, NULL );
+ ok( hr == S_OK, "got %08x\n", hr );
+ init_xmlstring( "u", &localname );
+ init_xmlstring( "ns", &ns );
+ call_count = 0;
+ hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
+ ok( hr == S_OK, "got %08x\n", hr );
+ hr = WsWriteEndElement( writer, NULL );
+ ok( hr == S_OK, "got %08x\n", hr );
+ ok( call_count == 2, "got %u\n", call_count );
+ check_output_bin( writer, res6, sizeof(res6), __LINE__ );
+
+ /* unknown string, error return from callback */
+ hr = WsSetOutput( writer, &bin.encoding, &buf.output, NULL, 0, NULL );
+ ok( hr == S_OK, "got %08x\n", hr );
+ init_xmlstring( "v", &localname );
+ init_xmlstring( "ns", &ns );
+ call_count = 0;
+ hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
+ ok( hr == S_OK, "got %08x\n", hr );
+ hr = WsWriteEndElement( writer, NULL );
+ ok( hr == S_OK, "got %08x\n", hr );
+ ok( call_count == 2, "got %u\n", call_count );
+ check_output_bin( writer, res7, sizeof(res7), __LINE__ );
+
WsFreeWriter( writer );
}
diff --git a/dlls/webservices/writer.c b/dlls/webservices/writer.c
index 67ae1b7..9c479b2 100644
--- a/dlls/webservices/writer.c
+++ b/dlls/webservices/writer.c
@@ -85,6 +85,8 @@ struct writer
struct xmlbuf *output_buf;
WS_HEAP *output_heap;
WS_XML_DICTIONARY *dict;
+ WS_DYNAMIC_STRING_CALLBACK dict_cb;
+ void *dict_cb_state;
ULONG prop_count;
struct prop prop[sizeof(writer_props)/sizeof(writer_props[0])];
};
@@ -168,6 +170,8 @@ static HRESULT init_writer( struct writer *writer )
writer->output_enc = WS_XML_WRITER_ENCODING_TYPE_TEXT;
writer->output_charset = WS_CHARSET_UTF8;
writer->dict = NULL;
+ writer->dict_cb = NULL;
+ writer->dict_cb_state = NULL;
return S_OK;
}
@@ -388,6 +392,8 @@ HRESULT WINAPI WsSetOutput( WS_XML_WRITER *handle, const WS_XML_WRITER_ENCODING
writer->output_enc = WS_XML_WRITER_ENCODING_TYPE_BINARY;
writer->output_charset = 0;
writer->dict = bin->staticDictionary;
+ writer->dict_cb = bin->dynamicStringCallback;
+ writer->dict_cb_state = bin->dynamicStringCallbackState;
break;
}
default:
@@ -638,8 +644,8 @@ static HRESULT write_string( struct writer *writer, const BYTE *bytes, ULONG len
static HRESULT write_dict_string( struct writer *writer, ULONG id )
{
HRESULT hr;
- if (id > 0x3fffffff) return E_INVALIDARG;
- if ((hr = write_int31( writer, id << 1 )) != S_OK) return hr;
+ if (id > 0x7fffffff) return E_INVALIDARG;
+ if ((hr = write_int31( writer, id )) != S_OK) return hr;
return S_OK;
}
@@ -678,6 +684,23 @@ static HRESULT write_attribute_value_bin( struct writer *writer, const WS_XML_TE
}
}
+static BOOL lookup_string_id( struct writer *writer, const WS_XML_STRING *str, ULONG *id )
+{
+ if (writer->dict && str->dictionary == writer->dict)
+ {
+ *id = str->id << 1;
+ return TRUE;
+ }
+ if (writer->dict_cb)
+ {
+ BOOL found = FALSE;
+ writer->dict_cb( writer->dict_cb_state, str, &found, id, NULL );
+ if (found) *id = (*id << 1) | 1;
+ return found;
+ }
+ return FALSE;
+}
+
static enum record_type get_attr_record_type( const WS_XML_ATTRIBUTE *attr, BOOL use_dict )
{
if (!attr->prefix || !attr->prefix->length)
@@ -696,8 +719,8 @@ static enum record_type get_attr_record_type( const WS_XML_ATTRIBUTE *attr, BOOL
static HRESULT write_attribute_bin( struct writer *writer, const WS_XML_ATTRIBUTE *attr )
{
- BOOL use_dict = (writer->dict && attr->localName->dictionary == writer->dict);
- enum record_type type = get_attr_record_type( attr, use_dict );
+ ULONG id;
+ enum record_type type = get_attr_record_type( attr, lookup_string_id(writer, attr->localName, &id) );
HRESULT hr;
if ((hr = write_grow_buffer( writer, 1 )) != S_OK) return hr;
@@ -710,7 +733,7 @@ static HRESULT write_attribute_bin( struct writer *writer, const WS_XML_ATTRIBUT
}
if (type >= RECORD_PREFIX_DICTIONARY_ATTRIBUTE_A && type <= RECORD_PREFIX_DICTIONARY_ATTRIBUTE_Z)
{
- if ((hr = write_dict_string( writer, attr->localName->id )) != S_OK) return hr;
+ if ((hr = write_dict_string( writer, id )) != S_OK) return hr;
return write_attribute_value_bin( writer, attr->value );
}
@@ -726,12 +749,12 @@ static HRESULT write_attribute_bin( struct writer *writer, const WS_XML_ATTRIBUT
break;
case RECORD_SHORT_DICTIONARY_ATTRIBUTE:
- if ((hr = write_dict_string( writer, attr->localName->id )) != S_OK) return hr;
+ if ((hr = write_dict_string( writer, id )) != S_OK) return hr;
break;
case RECORD_DICTIONARY_ATTRIBUTE:
if ((hr = write_string( writer, attr->prefix->bytes, attr->prefix->length )) != S_OK) return hr;
- if ((hr = write_dict_string( writer, attr->localName->id )) != S_OK) return hr;
+ if ((hr = write_dict_string( writer, id )) != S_OK) return hr;
break;
default:
@@ -844,8 +867,8 @@ static enum record_type get_xmlns_record_type( const WS_XML_ATTRIBUTE *attr, BOO
static HRESULT write_namespace_attribute_bin( struct writer *writer, const WS_XML_ATTRIBUTE *attr )
{
- BOOL use_dict = (writer->dict && attr->ns->dictionary == writer->dict);
- enum record_type type = get_xmlns_record_type( attr, use_dict );
+ ULONG id;
+ enum record_type type = get_xmlns_record_type( attr, lookup_string_id(writer, attr->ns, &id) );
HRESULT hr;
if ((hr = write_grow_buffer( writer, 1 )) != S_OK) return hr;
@@ -861,11 +884,11 @@ static HRESULT write_namespace_attribute_bin( struct writer *writer, const WS_XM
break;
case RECORD_SHORT_DICTIONARY_XMLNS_ATTRIBUTE:
- return write_dict_string( writer, attr->ns->id );
+ return write_dict_string( writer, id );
case RECORD_DICTIONARY_XMLNS_ATTRIBUTE:
if ((hr = write_string( writer, attr->prefix->bytes, attr->prefix->length )) != S_OK) return hr;
- return write_dict_string( writer, attr->ns->id );
+ return write_dict_string( writer, id );
default:
ERR( "unhandled record type %02x\n", type );
@@ -1063,8 +1086,8 @@ static enum record_type get_elem_record_type( const WS_XML_ELEMENT_NODE *elem, B
static HRESULT write_startelement_bin( struct writer *writer )
{
const WS_XML_ELEMENT_NODE *elem = &writer->current->hdr;
- BOOL use_dict = (writer->dict && elem->localName->dictionary == writer->dict);
- enum record_type type = get_elem_record_type( elem, use_dict );
+ ULONG id;
+ enum record_type type = get_elem_record_type( elem, lookup_string_id(writer, elem->localName, &id) );
HRESULT hr;
if ((hr = write_grow_buffer( writer, 1 )) != S_OK) return hr;
@@ -1077,7 +1100,7 @@ static HRESULT write_startelement_bin( struct writer *writer )
}
if (type >= RECORD_PREFIX_DICTIONARY_ELEMENT_A && type <= RECORD_PREFIX_DICTIONARY_ELEMENT_Z)
{
- if ((hr = write_dict_string( writer, elem->localName->id )) != S_OK) return hr;
+ if ((hr = write_dict_string( writer, id )) != S_OK) return hr;
return write_attributes( writer, elem );
}
@@ -1093,12 +1116,12 @@ static HRESULT write_startelement_bin( struct writer *writer )
break;
case RECORD_SHORT_DICTIONARY_ELEMENT:
- if ((hr = write_dict_string( writer, elem->localName->id )) != S_OK) return hr;
+ if ((hr = write_dict_string( writer, id )) != S_OK) return hr;
break;
case RECORD_DICTIONARY_ELEMENT:
if ((hr = write_string( writer, elem->prefix->bytes, elem->prefix->length )) != S_OK) return hr;
- if ((hr = write_dict_string( writer, elem->localName->id )) != S_OK) return hr;
+ if ((hr = write_dict_string( writer, id )) != S_OK) return hr;
break;
default:
--
2.1.4
More information about the wine-patches
mailing list