Commit 5154290a authored by Hans Leidekker's avatar Hans Leidekker Committed by Alexandre Julliard

webservices: Add a static builtin dictionary.

parent 58d527ef
......@@ -10,5 +10,6 @@ C_SRCS = \
msg.c \
proxy.c \
reader.c \
string.c \
url.c \
writer.c
......@@ -29,12 +29,6 @@
WINE_DEFAULT_DEBUG_CHANNEL(webservices);
const char *debugstr_xmlstr( const WS_XML_STRING *str )
{
if (!str) return "(null)";
return debugstr_an( (const char *)str->bytes, str->length );
}
ULONG prop_size( const struct prop_desc *desc, ULONG count )
{
ULONG i, ret = count * sizeof(struct prop);
......@@ -70,220 +64,6 @@ HRESULT prop_get( const struct prop *prop, ULONG count, ULONG id, void *buf, ULO
return S_OK;
}
static CRITICAL_SECTION dict_cs;
static CRITICAL_SECTION_DEBUG dict_cs_debug =
{
0, 0, &dict_cs,
{&dict_cs_debug.ProcessLocksList,
&dict_cs_debug.ProcessLocksList},
0, 0, {(DWORD_PTR)(__FILE__ ": dict_cs")}
};
static CRITICAL_SECTION dict_cs = {&dict_cs_debug, -1, 0, 0, 0, 0};
static ULONG dict_size, *dict_sorted;
static WS_XML_DICTIONARY dict_builtin =
{
{0x82704485,0x222a,0x4f7c,{0xb9,0x7b,0xe9,0xa4,0x62,0xa9,0x66,0x2b}}
};
/**************************************************************************
* WsGetDictionary [webservices.@]
*/
HRESULT WINAPI WsGetDictionary( WS_ENCODING encoding, WS_XML_DICTIONARY **dict, WS_ERROR *error )
{
TRACE( "%u %p %p\n", encoding, dict, error );
if (error) FIXME( "ignoring error parameter\n" );
if (!dict) return E_INVALIDARG;
if (encoding == WS_ENCODING_XML_BINARY_1 || encoding == WS_ENCODING_XML_BINARY_SESSION_1)
*dict = &dict_builtin;
else
*dict = NULL;
return S_OK;
}
static inline int cmp_string( const unsigned char *str, ULONG len, const unsigned char *str2, ULONG len2 )
{
if (len < len2) return -1;
else if (len > len2) return 1;
while (len--)
{
if (*str == *str2) { str++; str2++; }
else return *str - *str2;
}
return 0;
}
/* return -1 and string id if found, sort index if not found */
static int find_string( const unsigned char *data, ULONG len, ULONG *id )
{
int i, c, min = 0, max = dict_builtin.stringCount - 1;
while (min <= max)
{
i = (min + max) / 2;
c = cmp_string( data, len,
dict_builtin.strings[dict_sorted[i]].bytes,
dict_builtin.strings[dict_sorted[i]].length );
if (c < 0)
max = i - 1;
else if (c > 0)
min = i + 1;
else
{
*id = dict_builtin.strings[dict_sorted[i]].id;
return -1;
}
}
return max + 1;
}
#define MIN_DICTIONARY_SIZE 256
#define MAX_DICTIONARY_SIZE 2048
static BOOL grow_dict( ULONG size )
{
WS_XML_STRING *tmp;
ULONG new_size, *tmp_sorted;
if (dict_size >= dict_builtin.stringCount + size) return TRUE;
if (dict_size + size > MAX_DICTIONARY_SIZE) return FALSE;
if (!dict_builtin.strings)
{
new_size = max( MIN_DICTIONARY_SIZE, size );
if (!(dict_builtin.strings = heap_alloc( new_size * sizeof(WS_XML_STRING) ))) return FALSE;
if (!(dict_sorted = heap_alloc( new_size * sizeof(ULONG) )))
{
heap_free( dict_builtin.strings );
dict_builtin.strings = NULL;
return FALSE;
}
dict_size = new_size;
return TRUE;
}
new_size = max( dict_size * 2, size );
if (!(tmp = heap_realloc( dict_builtin.strings, new_size * sizeof(*tmp) ))) return FALSE;
dict_builtin.strings = tmp;
if (!(tmp_sorted = heap_realloc( dict_sorted, new_size * sizeof(*tmp_sorted) ))) return FALSE;
dict_sorted = tmp_sorted;
dict_size = new_size;
return TRUE;
}
static BOOL insert_string( unsigned char *data, ULONG len, int i, ULONG *ret_id )
{
ULONG id = dict_builtin.stringCount;
if (!grow_dict( 1 )) return FALSE;
memmove( &dict_sorted[i] + 1, &dict_sorted[i], (dict_builtin.stringCount - i) * sizeof(WS_XML_STRING *) );
dict_sorted[i] = id;
dict_builtin.strings[id].length = len;
dict_builtin.strings[id].bytes = data;
dict_builtin.strings[id].dictionary = &dict_builtin;
dict_builtin.strings[id].id = id;
dict_builtin.stringCount++;
*ret_id = id;
return TRUE;
}
static HRESULT add_xml_string( WS_XML_STRING *str )
{
int index;
ULONG id;
if (str->dictionary) return S_OK;
EnterCriticalSection( &dict_cs );
if ((index = find_string( str->bytes, str->length, &id )) == -1)
{
heap_free( str->bytes );
*str = dict_builtin.strings[id];
LeaveCriticalSection( &dict_cs );
return S_OK;
}
if (insert_string( str->bytes, str->length, index, &id ))
{
*str = dict_builtin.strings[id];
LeaveCriticalSection( &dict_cs );
return S_OK;
}
LeaveCriticalSection( &dict_cs );
return WS_E_QUOTA_EXCEEDED;
}
WS_XML_STRING *alloc_xml_string( const unsigned char *data, ULONG len )
{
WS_XML_STRING *ret;
if (!(ret = heap_alloc_zero( sizeof(*ret) ))) return NULL;
if ((ret->length = len) && !(ret->bytes = heap_alloc( len )))
{
heap_free( ret );
return NULL;
}
if (data)
{
memcpy( ret->bytes, data, len );
if (add_xml_string( ret ) != S_OK) WARN( "string not added to dictionary\n" );
}
return ret;
}
void free_xml_string( WS_XML_STRING *str )
{
if (!str) return;
if (!str->dictionary) heap_free( str->bytes );
heap_free( str );
}
WS_XML_STRING *dup_xml_string( const WS_XML_STRING *src )
{
WS_XML_STRING *ret;
unsigned char *data;
int index;
ULONG id;
if (!(ret = heap_alloc( sizeof(*ret) ))) return NULL;
if (src->dictionary)
{
*ret = *src;
return ret;
}
EnterCriticalSection( &dict_cs );
if ((index = find_string( src->bytes, src->length, &id )) == -1)
{
*ret = dict_builtin.strings[id];
LeaveCriticalSection( &dict_cs );
return ret;
}
if (!(data = heap_alloc( src->length )))
{
heap_free( ret );
LeaveCriticalSection( &dict_cs );
return NULL;
}
memcpy( data, src->bytes, src->length );
if (insert_string( data, src->length, index, &id ))
{
*ret = dict_builtin.strings[id];
LeaveCriticalSection( &dict_cs );
return ret;
}
LeaveCriticalSection( &dict_cs );
WARN( "string not added to dictionary\n" );
ret->length = src->length;
ret->bytes = data;
ret->dictionary = NULL;
ret->id = 0;
return ret;
}
struct node *alloc_node( WS_XML_NODE_TYPE type )
{
struct node *ret;
......@@ -590,6 +370,7 @@ struct reader
const unsigned char *input_data;
ULONG input_size;
ULONG text_conv_offset;
const WS_XML_DICTIONARY *dict_static;
WS_XML_DICTIONARY *dict;
ULONG prop_count;
struct prop prop[sizeof(reader_props)/sizeof(reader_props[0])];
......@@ -730,7 +511,8 @@ 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 = &dict_builtin;
reader->dict_static = NULL;
reader->dict = NULL;
return S_OK;
}
......@@ -1466,12 +1248,15 @@ static HRESULT read_string( struct reader *reader, WS_XML_STRING **str )
static HRESULT read_dict_string( struct reader *reader, WS_XML_STRING **str )
{
ULONG id;
const WS_XML_DICTIONARY *dict;
HRESULT hr;
ULONG id;
if ((hr = read_int31( reader, &id )) != S_OK) return hr;
if (!reader->dict || (id >>= 1) >= reader->dict->stringCount) return WS_E_INVALID_FORMAT;
dict = (id & 1) ? reader->dict : reader->dict_static;
if (!dict || (id >>= 1) >= dict->stringCount) return WS_E_INVALID_FORMAT;
if (!(*str = alloc_xml_string( NULL, 0 ))) return E_OUTOFMEMORY;
*(*str) = reader->dict->strings[id];
*(*str) = dict->strings[id];
return S_OK;
}
......@@ -5556,7 +5341,8 @@ HRESULT WINAPI WsSetInput( WS_XML_READER *handle, const WS_XML_READER_ENCODING *
{
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;
reader->dict_static = bin->staticDictionary ? bin->staticDictionary : &dict_builtin_static;
reader->dict = bin->dynamicDictionary ? bin->dynamicDictionary : &dict_builtin;
break;
}
default:
......@@ -5639,21 +5425,6 @@ done:
}
/**************************************************************************
* WsXmlStringEquals [webservices.@]
*/
HRESULT WINAPI WsXmlStringEquals( const WS_XML_STRING *str1, const WS_XML_STRING *str2, WS_ERROR *error )
{
TRACE( "%s %s %p\n", debugstr_xmlstr(str1), debugstr_xmlstr(str2), error );
if (error) FIXME( "ignoring error parameter\n" );
if (!str1 || !str2) return E_INVALIDARG;
if (str1->length != str2->length) return S_FALSE;
if (!memcmp( str1->bytes, str2->bytes, str1->length )) return S_OK;
return S_FALSE;
}
/**************************************************************************
* WsGetReaderPosition [webservices.@]
*/
HRESULT WINAPI WsGetReaderPosition( WS_XML_READER *handle, WS_XML_NODE_POSITION *pos, WS_ERROR *error )
......
......@@ -1340,12 +1340,12 @@ static void test_WsReadNode(void)
ok( hr == S_OK, "got %08x\n", hr );
ok( dict == NULL, "got %p\n", dict );
dict = (WS_XML_DICTIONARY *)0xdeadbeef;
dict = NULL;
hr = WsGetDictionary( WS_ENCODING_XML_BINARY_1, &dict, NULL );
ok( hr == S_OK, "got %08x\n", hr );
ok( dict != NULL, "dict not set\n" );
dict = (WS_XML_DICTIONARY *)0xdeadbeef;
dict = NULL;
hr = WsGetDictionary( WS_ENCODING_XML_BINARY_SESSION_1, &dict, NULL );
ok( hr == S_OK, "got %08x\n", hr );
ok( dict != NULL, "dict not set\n" );
......@@ -4897,6 +4897,8 @@ static void test_binary_encoding(void)
static void test_dictionary(void)
{
static const GUID dict_static =
{0xf93578f8,0x5852,0x4eb7,{0xa6,0xfc,0xe7,0x2b,0xb7,0x1d,0xb6,0x22}};
static const char res[] =
{0x42,0x04,0x01};
static const char res2[] =
......@@ -5190,17 +5192,22 @@ static void test_dictionary(void)
ok( hr == S_OK, "got %08x\n", hr );
ok( dict2 == NULL, "got %p\n", dict2 );
dict2 = (WS_XML_DICTIONARY *)0xdeadbeef;
dict2 = NULL;
hr = WsGetDictionary( WS_ENCODING_XML_BINARY_1, &dict2, NULL );
ok( hr == S_OK, "got %08x\n", hr );
ok( dict2 != NULL, "dict2 not set\n" );
ok( dict2 != &dict, "got %p\n", dict2 );
dict2 = (WS_XML_DICTIONARY *)0xdeadbeef;
dict2 = NULL;
hr = WsGetDictionary( WS_ENCODING_XML_BINARY_SESSION_1, &dict2, NULL );
ok( hr == S_OK, "got %08x\n", hr );
ok( dict2 != NULL, "dict2 not set\n" );
ok( dict2 != &dict, "got %p\n", dict2 );
ok( !memcmp( &dict2->guid, &dict_static, sizeof(dict_static) ),
"got %s\n", wine_dbgstr_guid(&dict2->guid) );
ok( dict2->stringCount == 488 || dict2->stringCount == 487 /* < win10 */, "got %u\n", dict2->stringCount );
ok( dict2->strings[0].length == 14, "got %u\n", dict2->strings[0].length );
ok( !memcmp( dict2->strings[0].bytes, "mustUnderstand", 14 ), "wrong data\n" );
WsFreeReader( reader );
}
......
......@@ -33,9 +33,13 @@ void ws_free( WS_HEAP *, void *, SIZE_T ) DECLSPEC_HIDDEN;
struct xmlbuf *alloc_xmlbuf( WS_HEAP * ) DECLSPEC_HIDDEN;
void free_xmlbuf( struct xmlbuf * ) DECLSPEC_HIDDEN;
WS_XML_DICTIONARY dict_builtin DECLSPEC_HIDDEN;
const WS_XML_DICTIONARY dict_builtin_static DECLSPEC_HIDDEN;
const char *debugstr_xmlstr( const WS_XML_STRING * ) DECLSPEC_HIDDEN;
WS_XML_STRING *alloc_xml_string( const unsigned char *, ULONG ) DECLSPEC_HIDDEN;
WS_XML_STRING *dup_xml_string( const WS_XML_STRING * ) DECLSPEC_HIDDEN;
HRESULT add_xml_string( WS_XML_STRING * ) DECLSPEC_HIDDEN;
void free_xml_string( WS_XML_STRING * ) DECLSPEC_HIDDEN;
WS_XML_UTF8_TEXT *alloc_utf8_text( const unsigned char *, ULONG ) DECLSPEC_HIDDEN;
HRESULT append_attribute( WS_XML_ELEMENT_NODE *, WS_XML_ATTRIBUTE * ) DECLSPEC_HIDDEN;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment