xmllite: Add a name stack for elements.

This commit is contained in:
Nikolay Sivov 2013-01-20 23:46:25 +04:00 committed by Alexandre Julliard
parent c525cf381d
commit 77735419eb
2 changed files with 68 additions and 4 deletions

View File

@ -124,6 +124,12 @@ struct attribute
strval value; strval value;
}; };
struct element
{
struct list entry;
strval qname;
};
typedef struct typedef struct
{ {
IXmlReader IXmlReader_iface; IXmlReader IXmlReader_iface;
@ -138,6 +144,7 @@ typedef struct
struct list attrs; /* attributes list for current node */ struct list attrs; /* attributes list for current node */
struct attribute *attr; /* current attribute */ struct attribute *attr; /* current attribute */
UINT attr_count; UINT attr_count;
struct list elements;
strval strvalues[StringValue_Last]; strval strvalues[StringValue_Last];
} xmlreader; } xmlreader;
@ -194,6 +201,21 @@ static inline void reader_free(xmlreader *reader, void *mem)
m_free(reader->imalloc, mem); m_free(reader->imalloc, mem);
} }
static HRESULT reader_strvaldup(xmlreader *reader, const strval *src, strval *dest)
{
*dest = *src;
if (src->str != strval_empty.str)
{
dest->str = reader_alloc(reader, (dest->len+1)*sizeof(WCHAR));
if (!dest->str) return E_OUTOFMEMORY;
memcpy(dest->str, src->str, dest->len*sizeof(WCHAR));
dest->str[dest->len] = 0;
}
return S_OK;
}
/* reader input memory allocation functions */ /* reader input memory allocation functions */
static inline void *readerinput_alloc(xmlreaderinput *input, size_t len) static inline void *readerinput_alloc(xmlreaderinput *input, size_t len)
{ {
@ -253,10 +275,9 @@ static HRESULT reader_add_attr(xmlreader *reader, strval *localname, strval *val
return S_OK; return S_OK;
} }
static void reader_free_strvalue(xmlreader *reader, XmlReaderStringValue type) /* This one frees stored string value if needed */
static void reader_free_strvalued(xmlreader *reader, strval *v)
{ {
strval *v = &reader->strvalues[type];
if (v->str != strval_empty.str) if (v->str != strval_empty.str)
{ {
reader_free(reader, v->str); reader_free(reader, v->str);
@ -264,6 +285,11 @@ static void reader_free_strvalue(xmlreader *reader, XmlReaderStringValue type)
} }
} }
static void reader_free_strvalue(xmlreader *reader, XmlReaderStringValue type)
{
reader_free_strvalued(reader, &reader->strvalues[type]);
}
static void reader_free_strvalues(xmlreader *reader) static void reader_free_strvalues(xmlreader *reader)
{ {
int type; int type;
@ -271,6 +297,32 @@ static void reader_free_strvalues(xmlreader *reader)
reader_free_strvalue(reader, type); reader_free_strvalue(reader, type);
} }
static void reader_clear_elements(xmlreader *reader)
{
struct element *elem, *elem2;
LIST_FOR_EACH_ENTRY_SAFE(elem, elem2, &reader->elements, struct element, entry)
{
reader_free_strvalued(reader, &elem->qname);
reader_free(reader, elem);
}
list_init(&reader->elements);
}
static HRESULT reader_push_element(xmlreader *reader, strval *qname)
{
struct element *elem;
HRESULT hr;
elem = reader_alloc(reader, sizeof(*elem));
if (!elem) return E_OUTOFMEMORY;
hr = reader_strvaldup(reader, qname, &elem->qname);
if (FAILED(hr)) return hr;
list_add_head(&reader->elements, &elem->entry);
return hr;
}
/* always make a copy, cause strings are supposed to be null terminated */ /* always make a copy, cause strings are supposed to be null terminated */
static void reader_set_strvalue(xmlreader *reader, XmlReaderStringValue type, const strval *value) static void reader_set_strvalue(xmlreader *reader, XmlReaderStringValue type, const strval *value)
{ {
@ -1398,6 +1450,7 @@ static HRESULT reader_parse_qname(xmlreader *reader, strval *prefix, strval *loc
static HRESULT reader_parse_stag(xmlreader *reader, strval *prefix, strval *local, strval *qname) static HRESULT reader_parse_stag(xmlreader *reader, strval *prefix, strval *local, strval *qname)
{ {
static const WCHAR endW[] = {'/','>',0}; static const WCHAR endW[] = {'/','>',0};
static const WCHAR gtW[] = {'>',0};
HRESULT hr; HRESULT hr;
/* skip '<' */ /* skip '<' */
@ -1410,7 +1463,11 @@ static HRESULT reader_parse_stag(xmlreader *reader, strval *prefix, strval *loca
if (!reader_cmp(reader, endW)) return S_OK; if (!reader_cmp(reader, endW)) return S_OK;
FIXME("only empty elements without attributes supported\n"); /* got a start tag */
if (!reader_cmp(reader, gtW))
return reader_push_element(reader, qname);
FIXME("only empty elements/start tags without attribute list supported\n");
return E_NOTIMPL; return E_NOTIMPL;
} }
@ -1561,6 +1618,7 @@ static ULONG WINAPI xmlreader_Release(IXmlReader *iface)
IMalloc *imalloc = This->imalloc; IMalloc *imalloc = This->imalloc;
if (This->input) IUnknown_Release(&This->input->IXmlReaderInput_iface); if (This->input) IUnknown_Release(&This->input->IXmlReaderInput_iface);
reader_clear_attrs(This); reader_clear_attrs(This);
reader_clear_elements(This);
reader_free_strvalues(This); reader_free_strvalues(This);
reader_free(This, This); reader_free(This, This);
if (imalloc) IMalloc_Release(imalloc); if (imalloc) IMalloc_Release(imalloc);
@ -1985,6 +2043,7 @@ HRESULT WINAPI CreateXmlReader(REFIID riid, void **obj, IMalloc *imalloc)
list_init(&reader->attrs); list_init(&reader->attrs);
reader->attr_count = 0; reader->attr_count = 0;
reader->attr = NULL; reader->attr = NULL;
list_init(&reader->elements);
for (i = 0; i < StringValue_Last; i++) for (i = 0; i < StringValue_Last; i++)
reader->strvalues[i] = strval_empty; reader->strvalues[i] = strval_empty;

View File

@ -888,6 +888,7 @@ static const char misc_test_xml[] =
"<!-- comment3 -->" "<!-- comment3 -->"
" \t \r \n" " \t \r \n"
"<!-- comment4 -->" "<!-- comment4 -->"
"<a>"
; ;
static struct nodes_test misc_test = { static struct nodes_test misc_test = {
@ -899,6 +900,7 @@ static struct nodes_test misc_test = {
XmlNodeType_Comment, XmlNodeType_Comment,
XmlNodeType_Whitespace, XmlNodeType_Whitespace,
XmlNodeType_Comment, XmlNodeType_Comment,
XmlNodeType_Element,
XmlNodeType_None XmlNodeType_None
} }
}; };
@ -1028,6 +1030,9 @@ static struct test_entry element_tests[] = {
{ "<a:b/>", "a:b", "", NC_E_UNDECLAREDPREFIX }, { "<a:b/>", "a:b", "", NC_E_UNDECLAREDPREFIX },
{ "<:a/>", NULL, NULL, NC_E_QNAMECHARACTER }, { "<:a/>", NULL, NULL, NC_E_QNAMECHARACTER },
{ "< a/>", NULL, NULL, NC_E_QNAMECHARACTER }, { "< a/>", NULL, NULL, NC_E_QNAMECHARACTER },
{ "<a>", "a", "", S_OK },
{ "<a >", "a", "", S_OK },
{ "<a \r \t\n>", "a", "", S_OK },
{ NULL } { NULL }
}; };