webservices: Add support for reading attributes in binary mode.
Signed-off-by: Hans Leidekker <hans@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
505d60f988
commit
78428d963e
|
@ -1221,6 +1221,11 @@ error:
|
|||
return hr;
|
||||
}
|
||||
|
||||
static inline BOOL is_text_type( unsigned char type )
|
||||
{
|
||||
return (type >= RECORD_ZERO_TEXT && type <= RECORD_QNAME_DICTIONARY_TEXT_WITH_ENDELEMENT);
|
||||
}
|
||||
|
||||
static HRESULT read_int31( struct reader *reader, ULONG *len )
|
||||
{
|
||||
unsigned char byte;
|
||||
|
@ -1258,6 +1263,42 @@ static HRESULT read_string( struct reader *reader, WS_XML_STRING **str )
|
|||
return hr;
|
||||
}
|
||||
|
||||
static HRESULT read_attribute_value_bin( struct reader *reader, WS_XML_ATTRIBUTE *attr )
|
||||
{
|
||||
WS_XML_UTF8_TEXT *utf8 = NULL;
|
||||
unsigned char type;
|
||||
HRESULT hr;
|
||||
ULONG len;
|
||||
|
||||
if ((hr = read_byte( reader, &type )) != S_OK) return hr;
|
||||
if (!is_text_type( type )) return WS_E_INVALID_FORMAT;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case RECORD_CHARS8_TEXT:
|
||||
{
|
||||
unsigned char len8;
|
||||
if ((hr = read_byte( reader, &len8 )) != S_OK) return hr;
|
||||
len = len8;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
ERR( "unhandled record type %02x\n", type );
|
||||
return WS_E_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
if (!(utf8 = alloc_utf8_text( NULL, len ))) return E_OUTOFMEMORY;
|
||||
if (!len) utf8->value.bytes = (BYTE *)(utf8 + 1); /* quirk */
|
||||
if ((hr = read_bytes( reader, utf8->value.bytes, len )) != S_OK)
|
||||
{
|
||||
heap_free( utf8 );
|
||||
return hr;
|
||||
}
|
||||
|
||||
attr->value = &utf8->text;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static HRESULT read_attribute_text( struct reader *reader, WS_XML_ATTRIBUTE **ret )
|
||||
{
|
||||
static const WS_XML_STRING xmlns = {5, (BYTE *)"xmlns"};
|
||||
|
@ -1314,6 +1355,83 @@ error:
|
|||
return hr;
|
||||
}
|
||||
|
||||
static inline BOOL is_attribute_type( unsigned char type )
|
||||
{
|
||||
return (type >= RECORD_SHORT_ATTRIBUTE && type <= RECORD_PREFIX_ATTRIBUTE_Z);
|
||||
}
|
||||
|
||||
static HRESULT read_attribute_bin( struct reader *reader, WS_XML_ATTRIBUTE **ret )
|
||||
{
|
||||
WS_XML_ATTRIBUTE *attr;
|
||||
unsigned char type = 0;
|
||||
HRESULT hr;
|
||||
|
||||
if ((hr = read_byte( reader, &type )) != S_OK) return hr;
|
||||
if (!is_attribute_type( type )) return WS_E_INVALID_FORMAT;
|
||||
if (!(attr = heap_alloc_zero( sizeof(*attr) ))) return E_OUTOFMEMORY;
|
||||
|
||||
if (type >= RECORD_PREFIX_ATTRIBUTE_A && type <= RECORD_PREFIX_ATTRIBUTE_Z)
|
||||
{
|
||||
unsigned char ch = type - RECORD_PREFIX_ATTRIBUTE_A + 'a';
|
||||
if (!(attr->prefix = alloc_xml_string( &ch, 1 )))
|
||||
{
|
||||
hr = E_OUTOFMEMORY;
|
||||
goto error;
|
||||
}
|
||||
if ((hr = read_string( reader, &attr->localName )) != S_OK) goto error;
|
||||
if ((hr = read_attribute_value_bin( reader, attr )) != S_OK) goto error;
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case RECORD_SHORT_ATTRIBUTE:
|
||||
if (!(attr->prefix = alloc_xml_string( NULL, 0 )))
|
||||
{
|
||||
hr = E_OUTOFMEMORY;
|
||||
goto error;
|
||||
}
|
||||
if ((hr = read_string( reader, &attr->localName )) != S_OK) goto error;
|
||||
if ((hr = read_attribute_value_bin( reader, attr )) != S_OK) goto error;
|
||||
break;
|
||||
|
||||
case RECORD_ATTRIBUTE:
|
||||
if ((hr = read_string( reader, &attr->prefix )) != S_OK) goto error;
|
||||
if ((hr = read_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 )))
|
||||
{
|
||||
hr = E_OUTOFMEMORY;
|
||||
goto error;
|
||||
}
|
||||
if ((hr = read_string( reader, &attr->ns )) != S_OK) goto error;
|
||||
attr->isXmlNs = 1;
|
||||
break;
|
||||
|
||||
case RECORD_XMLNS_ATTRIBUTE:
|
||||
if ((hr = read_string( reader, &attr->prefix )) != S_OK) 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;
|
||||
|
||||
default:
|
||||
ERR( "unhandled record type %02x\n", type );
|
||||
return WS_E_NOT_SUPPORTED;
|
||||
}
|
||||
}
|
||||
|
||||
*ret = attr;
|
||||
return S_OK;
|
||||
|
||||
error:
|
||||
free_attribute( attr );
|
||||
return hr;
|
||||
}
|
||||
|
||||
static inline struct node *find_parent( struct reader *reader )
|
||||
{
|
||||
if (node_type( reader->current ) == WS_XML_NODE_TYPE_END_ELEMENT)
|
||||
|
@ -1438,6 +1556,28 @@ static inline BOOL is_element_type( unsigned char type )
|
|||
return (type >= RECORD_SHORT_ELEMENT && type <= RECORD_PREFIX_ELEMENT_Z);
|
||||
}
|
||||
|
||||
static HRESULT read_attributes_bin( struct reader *reader, WS_XML_ELEMENT_NODE *elem )
|
||||
{
|
||||
WS_XML_ATTRIBUTE *attr;
|
||||
unsigned char type;
|
||||
HRESULT hr;
|
||||
|
||||
reader->current_attr = 0;
|
||||
for (;;)
|
||||
{
|
||||
if ((hr = read_peek( reader, &type )) != S_OK) return hr;
|
||||
if (!is_attribute_type( type )) break;
|
||||
if ((hr = read_attribute_bin( reader, &attr )) != S_OK) return hr;
|
||||
if ((hr = append_attribute( elem, attr )) != S_OK)
|
||||
{
|
||||
free_attribute( attr );
|
||||
return hr;
|
||||
}
|
||||
reader->current_attr++;
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static HRESULT read_element_bin( struct reader *reader )
|
||||
{
|
||||
struct node *node = NULL, *parent;
|
||||
|
@ -1491,6 +1631,7 @@ static HRESULT read_element_bin( struct reader *reader )
|
|||
goto error;
|
||||
}
|
||||
|
||||
if ((hr = read_attributes_bin( reader, elem )) != S_OK) goto error;
|
||||
if ((hr = set_namespaces( reader, elem )) != S_OK) goto error;
|
||||
|
||||
read_insert_node( reader, parent, node );
|
||||
|
|
|
@ -4510,8 +4510,13 @@ static void test_binary_encoding(void)
|
|||
{
|
||||
static const char res[] =
|
||||
{0x40,0x01,'t',0x01};
|
||||
static const char res2[] =
|
||||
{0x6d,0x01,'t',0x09,0x01,'p',0x02,'n','s',0x01};
|
||||
static const char res3[] =
|
||||
{0x41,0x02,'p','2',0x01,'t',0x09,0x02,'p','2',0x02,'n','s',0x01};
|
||||
const WS_XML_NODE *node;
|
||||
const WS_XML_ELEMENT_NODE *elem;
|
||||
const WS_XML_ATTRIBUTE *attr;
|
||||
WS_XML_READER *reader;
|
||||
HRESULT hr;
|
||||
|
||||
|
@ -4543,6 +4548,70 @@ static void test_binary_encoding(void)
|
|||
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 element */
|
||||
hr = set_input_bin( reader, res2, sizeof(res2) );
|
||||
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, "t", 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" );
|
||||
|
||||
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 );
|
||||
|
||||
/* element */
|
||||
hr = set_input_bin( reader, res3, sizeof(res3) );
|
||||
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, "t", 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 == 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 );
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue