From: Nikolay Sivov Subject: [1/3] xmllite: Use buffer offset instead of pointers Message-Id: <52517C6B.8090605@codeweavers.com> Date: Sun, 06 Oct 2013 19:06:19 +0400 It's normal to grow destination buffer, in this case all stored pointers will be trashed. This patch uses offsets from start of a buffer instead. From 714ab56eeb0fe1e133227f0ec12818bf2d7ecb93 Mon Sep 17 00:00:00 2001 From: Nikolay Sivov Date: Sun, 6 Oct 2013 18:58:09 +0400 Subject: [PATCH 5/7] Use buffer offset instead of pointers --- dlls/xmllite/reader.c | 446 +++++++++++++++++++++++-------------------- dlls/xmllite/tests/reader.c | 1 + 2 files changed, 245 insertions(+), 202 deletions(-) diff --git a/dlls/xmllite/reader.c b/dlls/xmllite/reader.c index b181230..8bfa1a3 100644 --- a/dlls/xmllite/reader.c +++ b/dlls/xmllite/reader.c @@ -170,7 +170,7 @@ static const struct xml_encoding_data xml_encoding_map[] = { typedef struct { char *data; - char *cur; + UINT cur; unsigned int allocated; unsigned int written; } encoded_buffer; @@ -209,11 +209,11 @@ typedef struct { WCHAR *str; /* allocated null-terminated string */ UINT len; /* length in WCHARs, altered after ReadValueChunk */ - WCHAR *start; /* input position where value starts */ + UINT start; /* input position where value starts */ } strval; static WCHAR emptyW[] = {0}; -static const strval strval_empty = {emptyW, 0, emptyW}; +static const strval strval_empty = { emptyW }; struct attribute { @@ -249,7 +249,7 @@ typedef struct UINT depth; UINT max_depth; BOOL empty_element; - WCHAR *resume[XmlReadResume_Last]; /* pointers used to resume reader */ + UINT resume[XmlReadResume_Last]; /* offsets used to resume reader */ } xmlreader; struct input_buffer @@ -305,6 +305,18 @@ static inline void reader_free(xmlreader *reader, void *mem) m_free(reader->imalloc, mem); } +/* Just return pointer from offset, no attempt to read more. */ +static inline WCHAR *reader_get_ptr2(const xmlreader *reader, UINT offset) +{ + encoded_buffer *buffer = &reader->input->buffer->utf16; + return (WCHAR*)buffer->data + offset; +} + +static inline WCHAR *reader_get_strptr(const xmlreader *reader, const strval *v) +{ + return v->str ? v->str : reader_get_ptr2(reader, v->start); +} + static HRESULT reader_strvaldup(xmlreader *reader, const strval *src, strval *dest) { *dest = *src; @@ -313,8 +325,9 @@ static HRESULT reader_strvaldup(xmlreader *reader, const strval *src, strval *de { 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)); + memcpy(dest->str, reader_get_strptr(reader, src), dest->len*sizeof(WCHAR)); dest->str[dest->len] = 0; + dest->start = 0; } return S_OK; @@ -389,10 +402,30 @@ static void reader_free_strvalued(xmlreader *reader, strval *v) } } -static inline void reader_init_strvalue(WCHAR *str, UINT len, strval *v) +/* returns length in WCHARs from 'start' to current buffer offset */ +static inline UINT reader_get_len(const xmlreader *reader, UINT start) +{ + return reader->input->buffer->utf16.cur - start; +} + +static inline void reader_init_strvalue(UINT start, UINT len, strval *v) +{ + v->start = start; + v->len = len; + v->str = NULL; +} + +static inline const char* debug_strval(const xmlreader *reader, const strval *v) +{ + return debugstr_wn(reader_get_strptr(reader, v), v->len); +} + +/* used to initalize from constant string */ +static inline void reader_init_cstrvalue(WCHAR *str, UINT len, strval *v) { - v->start = v->str = str; + v->start = 0; v->len = len; + v->str = str; } static void reader_free_strvalue(xmlreader *reader, XmlReaderStringValue type) @@ -409,10 +442,10 @@ static void reader_free_strvalues(xmlreader *reader) /* This helper should only be used to test if strings are the same, it doesn't try to sort. */ -static inline int strval_eq(const strval *str1, const strval *str2) +static inline int strval_eq(const xmlreader *reader, const strval *str1, const strval *str2) { if (str1->len != str2->len) return 0; - return !memcmp(str1->str, str2->str, str1->len*sizeof(WCHAR)); + return !memcmp(reader_get_strptr(reader, str1), reader_get_strptr(reader, str2), str1->len*sizeof(WCHAR)); } static void reader_clear_elements(xmlreader *reader) @@ -498,7 +531,7 @@ static void reader_set_strvalue(xmlreader *reader, XmlReaderStringValue type, co if (!value) { v->str = NULL; - v->start = NULL; + v->start = 0; v->len = 0; return; } @@ -517,7 +550,7 @@ static void reader_set_strvalue(xmlreader *reader, XmlReaderStringValue type, co else { v->str = reader_alloc(reader, (value->len + 1)*sizeof(WCHAR)); - memcpy(v->str, value->start, value->len*sizeof(WCHAR)); + memcpy(v->str, reader_get_strptr(reader, value), value->len*sizeof(WCHAR)); v->str[value->len] = 0; v->len = value->len; } @@ -536,7 +569,7 @@ static HRESULT init_encoded_buffer(xmlreaderinput *input, encoded_buffer *buffer if (!buffer->data) return E_OUTOFMEMORY; memset(buffer->data, 0, 4); - buffer->cur = buffer->data; + buffer->cur = 0; buffer->allocated = initial_len; buffer->written = 0; @@ -778,8 +811,8 @@ static int readerinput_get_convlen(xmlreaderinput *readerinput) else len = buffer->written; - TRACE("%d\n", len - (int)(buffer->cur - buffer->data)); - return len - (buffer->cur - buffer->data); + TRACE("%d\n", len - buffer->cur); + return len - buffer->cur; } /* It's possible that raw buffer has some leftovers from last conversion - some char @@ -792,12 +825,12 @@ static void readerinput_shrinkraw(xmlreaderinput *readerinput, int len) if (len == -1) len = readerinput_get_convlen(readerinput); - memmove(buffer->data, buffer->cur + (buffer->written - len), len); + memmove(buffer->data, buffer->data + buffer->cur + (buffer->written - len), len); /* everything below cur is lost too */ - buffer->written -= len + (buffer->cur - buffer->data); - /* after this point we don't need cur pointer really, + buffer->written -= len + buffer->cur; + /* after this point we don't need cur offset really, it's used only to mark where actual data begins when first chunk is read */ - buffer->cur = buffer->data; + buffer->cur = 0; } /* note that raw buffer content is kept */ @@ -822,15 +855,15 @@ static void readerinput_switchencoding(xmlreaderinput *readerinput, xml_encoding if (enc == XmlEncoding_UTF16) { readerinput_grow(readerinput, len); - memcpy(dest->data, src->cur, len); + memcpy(dest->data, src->data + src->cur, len); dest->written += len*sizeof(WCHAR); return; } - dest_len = MultiByteToWideChar(cp, 0, src->cur, len, NULL, 0); + dest_len = MultiByteToWideChar(cp, 0, src->data + src->cur, len, NULL, 0); readerinput_grow(readerinput, dest_len); ptr = (WCHAR*)dest->data; - MultiByteToWideChar(cp, 0, src->cur, len, ptr, dest_len); + MultiByteToWideChar(cp, 0, src->data + src->cur, len, ptr, dest_len); ptr[dest_len] = 0; dest->written += dest_len*sizeof(WCHAR); } @@ -841,12 +874,12 @@ static void reader_shrink(xmlreader *reader) encoded_buffer *buffer = &reader->input->buffer->utf16; /* avoid to move too often using threshold shrink length */ - if (buffer->cur - buffer->data > buffer->written / 2) + if (buffer->cur*sizeof(WCHAR) > buffer->written / 2) { - buffer->written -= buffer->cur - buffer->data; - memmove(buffer->data, buffer->cur, buffer->written); - buffer->cur = buffer->data; - *(WCHAR*)&buffer->cur[buffer->written] = 0; + buffer->written -= buffer->cur*sizeof(WCHAR); + memmove(buffer->data, (WCHAR*)buffer->data + buffer->cur, buffer->written); + buffer->cur = 0; + *(WCHAR*)&buffer->data[buffer->written] = 0; } } @@ -870,15 +903,15 @@ static HRESULT reader_more(xmlreader *reader) if (cp == ~0) { readerinput_grow(readerinput, len); - memcpy(dest->data, src->cur, len); + memcpy(dest->data, src->data + src->cur, len); dest->written += len*sizeof(WCHAR); return hr; } - dest_len = MultiByteToWideChar(cp, 0, src->cur, len, NULL, 0); + dest_len = MultiByteToWideChar(cp, 0, src->data + src->cur, len, NULL, 0); readerinput_grow(readerinput, dest_len); ptr = (WCHAR*)dest->data; - MultiByteToWideChar(cp, 0, src->cur, len, ptr, dest_len); + MultiByteToWideChar(cp, 0, src->data + src->cur, len, ptr, dest_len); ptr[dest_len] = 0; dest->written += dest_len*sizeof(WCHAR); /* get rid of processed data */ @@ -887,16 +920,22 @@ static HRESULT reader_more(xmlreader *reader) return hr; } -static inline WCHAR *reader_get_cur(xmlreader *reader) +static inline UINT reader_get_cur(xmlreader *reader) { - WCHAR *ptr = (WCHAR*)reader->input->buffer->utf16.cur; + return reader->input->buffer->utf16.cur; +} + +static inline WCHAR *reader_get_ptr(xmlreader *reader) +{ + encoded_buffer *buffer = &reader->input->buffer->utf16; + WCHAR *ptr = (WCHAR*)buffer->data + buffer->cur; if (!*ptr) reader_more(reader); return ptr; } static int reader_cmp(xmlreader *reader, const WCHAR *str) { - const WCHAR *ptr = reader_get_cur(reader); + const WCHAR *ptr = reader_get_ptr(reader); return strncmpW(str, ptr, strlenW(str)); } @@ -904,11 +943,11 @@ static int reader_cmp(xmlreader *reader, const WCHAR *str) static void reader_skipn(xmlreader *reader, int n) { encoded_buffer *buffer = &reader->input->buffer->utf16; - const WCHAR *ptr = reader_get_cur(reader); + const WCHAR *ptr = reader_get_ptr(reader); while (*ptr++ && n--) { - buffer->cur += sizeof(WCHAR); + buffer->cur++; reader->pos++; } } @@ -922,11 +961,11 @@ static inline int is_wchar_space(WCHAR ch) static int reader_skipspaces(xmlreader *reader) { encoded_buffer *buffer = &reader->input->buffer->utf16; - const WCHAR *ptr = reader_get_cur(reader), *start = ptr; + const WCHAR *ptr = reader_get_ptr(reader), *start = ptr; while (is_wchar_space(*ptr)) { - buffer->cur += sizeof(WCHAR); + buffer->cur++; if (*ptr == '\r') reader->pos = 0; else if (*ptr == '\n') @@ -945,20 +984,21 @@ static int reader_skipspaces(xmlreader *reader) /* [26] VersionNum ::= '1.' [0-9]+ */ static HRESULT reader_parse_versionnum(xmlreader *reader, strval *val) { - WCHAR *ptr, *ptr2, *start = reader_get_cur(reader); static const WCHAR onedotW[] = {'1','.',0}; + WCHAR *ptr, *ptr2; + UINT start; if (reader_cmp(reader, onedotW)) return WC_E_XMLDECL; /* skip "1." */ reader_skipn(reader, 2); - ptr2 = ptr = reader_get_cur(reader); + ptr2 = ptr = reader_get_ptr(reader); while (*ptr >= '0' && *ptr <= '9') ptr++; if (ptr2 == ptr) return WC_E_DIGIT; - TRACE("version=%s\n", debugstr_wn(start, ptr-start)); - reader_init_strvalue(start, ptr-start, val); + reader_init_strvalue(start, reader_get_cur(reader)-start, val); + TRACE("version=%s\n", debug_strval(reader, val)); reader_skipn(reader, ptr-ptr2); return S_OK; } @@ -1022,7 +1062,7 @@ static inline int is_wchar_encname(WCHAR ch) /* [81] EncName ::= [A-Za-z] ([A-Za-z0-9._] | '-')* */ static HRESULT reader_parse_encname(xmlreader *reader, strval *val) { - WCHAR *start = reader_get_cur(reader), *ptr; + WCHAR *start = reader_get_ptr(reader), *ptr; xml_encoding enc; int len; @@ -1057,7 +1097,7 @@ static HRESULT reader_parse_encdecl(xmlreader *reader) if (!reader_skipspaces(reader)) return WC_E_WHITESPACE; if (reader_cmp(reader, encodingW)) return S_FALSE; - name.str = reader_get_cur(reader); + name.str = reader_get_ptr(reader); name.len = 8; /* skip 'encoding' */ reader_skipn(reader, 8); @@ -1088,8 +1128,9 @@ static HRESULT reader_parse_sddecl(xmlreader *reader) static const WCHAR standaloneW[] = {'s','t','a','n','d','a','l','o','n','e',0}; static const WCHAR yesW[] = {'y','e','s',0}; static const WCHAR noW[] = {'n','o',0}; - WCHAR *start, *ptr; strval name, val; + WCHAR *ptr; + UINT start; HRESULT hr; if (!reader_skipspaces(reader)) return WC_E_WHITESPACE; @@ -1113,10 +1154,9 @@ static HRESULT reader_parse_sddecl(xmlreader *reader) start = reader_get_cur(reader); /* skip 'yes'|'no' */ reader_skipn(reader, reader_cmp(reader, yesW) ? 2 : 3); - ptr = reader_get_cur(reader); - TRACE("standalone=%s\n", debugstr_wn(start, ptr-start)); - val.str = val.start = start; - val.len = ptr-start; + ptr = reader_get_ptr(reader); + reader_init_strvalue(start, reader_get_cur(reader)-start, &val); + TRACE("standalone=%s\n", debug_strval(reader, &val)); if (reader_cmp(reader, quoteW) && reader_cmp(reader, dblquoteW)) return WC_E_QUOTE; @@ -1165,19 +1205,21 @@ static HRESULT reader_parse_xmldecl(xmlreader *reader) /* [15] Comment ::= '' */ static HRESULT reader_parse_comment(xmlreader *reader) { - WCHAR *start, *ptr; + WCHAR *ptr; + UINT start; - if (reader->resume[XmlReadResume_Body]) + if (reader->resumestate == XmlReadResumeState_Comment) { start = reader->resume[XmlReadResume_Body]; - ptr = reader_get_cur(reader); + ptr = reader_get_ptr(reader); } else { /* skip '' */ + reader_init_strvalue(start, reader_get_cur(reader)-start, &value); + TRACE("%s\n", debug_strval(reader, &value)); + + /* skip rest of markup '->' */ reader_skipn(reader, 3); - reader_init_strvalue(start, ptr-start, &value); + reader_set_strvalue(reader, StringValue_LocalName, &strval_empty); reader_set_strvalue(reader, StringValue_QualifiedName, &strval_empty); reader_set_strvalue(reader, StringValue_Value, &value); - reader->resume[XmlReadResume_Body] = NULL; + reader->resume[XmlReadResume_Body] = 0; reader->resumestate = XmlReadResumeState_Initial; return S_OK; } else return WC_E_COMMENT; } - else - ptr++; - } - else - { - reader_skipn(reader, 1); - ptr++; } + + reader_skipn(reader, 1); + ptr++; } return S_OK; @@ -1313,23 +1353,25 @@ static XmlNodeType reader_get_nodetype(const xmlreader *reader) [5] Name ::= NameStartChar (NameChar)* */ static HRESULT reader_parse_name(xmlreader *reader, strval *name) { - WCHAR *ptr, *start; + WCHAR *ptr; + UINT start; if (reader->resume[XmlReadResume_Name]) { start = reader->resume[XmlReadResume_Name]; - ptr = reader_get_cur(reader); + ptr = reader_get_ptr(reader); } else { - ptr = start = reader_get_cur(reader); + ptr = reader_get_ptr(reader); + start = reader_get_cur(reader); if (!is_namestartchar(*ptr)) return WC_E_NAMECHARACTER; } while (is_namechar(*ptr)) { reader_skipn(reader, 1); - ptr = reader_get_cur(reader); + ptr = reader_get_ptr(reader); } if (is_reader_pending(reader)) @@ -1338,10 +1380,10 @@ static HRESULT reader_parse_name(xmlreader *reader, strval *name) return E_PENDING; } else - reader->resume[XmlReadResume_Name] = NULL; + reader->resume[XmlReadResume_Name] = 0; - TRACE("name %s:%d\n", debugstr_wn(start, ptr-start), (int)(ptr-start)); - reader_init_strvalue(start, ptr-start, name); + reader_init_strvalue(start, reader_get_cur(reader)-start, name); + TRACE("name %s:%d\n", debug_strval(reader, name), name->len); return S_OK; } @@ -1350,7 +1392,9 @@ static HRESULT reader_parse_name(xmlreader *reader, strval *name) static HRESULT reader_parse_pitarget(xmlreader *reader, strval *target) { static const WCHAR xmlW[] = {'x','m','l'}; + static const strval xmlval = { (WCHAR*)xmlW, 3 }; strval name; + WCHAR *ptr; HRESULT hr; UINT i; @@ -1358,15 +1402,16 @@ static HRESULT reader_parse_pitarget(xmlreader *reader, strval *target) if (FAILED(hr)) return is_reader_pending(reader) ? E_PENDING : WC_E_PI; /* now that we got name check for illegal content */ - if (name.len == 3 && !strncmpiW(name.str, xmlW, 3)) + if (strval_eq(reader, &name, &xmlval)) return WC_E_LEADINGXML; /* PITarget can't be a qualified name */ + ptr = reader_get_strptr(reader, &name); for (i = 0; i < name.len; i++) - if (name.str[i] == ':') + if (ptr[i] == ':') return i ? NC_E_NAMECOLON : WC_E_PI; - TRACE("pitarget %s:%d\n", debugstr_wn(name.str, name.len), name.len); + TRACE("pitarget %s:%d\n", debug_strval(reader, &name), name.len); *target = name; return S_OK; } @@ -1374,8 +1419,9 @@ static HRESULT reader_parse_pitarget(xmlreader *reader, strval *target) /* [16] PI ::= '' Char*)))? '?>' */ static HRESULT reader_parse_pi(xmlreader *reader) { - WCHAR *ptr, *start; strval target; + WCHAR *ptr; + UINT start; HRESULT hr; switch (reader->resumestate) @@ -1392,64 +1438,44 @@ static HRESULT reader_parse_pi(xmlreader *reader) reader_set_strvalue(reader, StringValue_QualifiedName, &target); reader_set_strvalue(reader, StringValue_Value, &strval_empty); reader->resumestate = XmlReadResumeState_PIBody; + reader->resume[XmlReadResume_Body] = reader_get_cur(reader); default: ; } - ptr = reader_get_cur(reader); - /* exit earlier if there's no content */ - if (ptr[0] == '?' && ptr[1] == '>') - { - /* skip '?>' */ - reader_skipn(reader, 2); - reader->nodetype = XmlNodeType_ProcessingInstruction; - reader->resumestate = XmlReadResumeState_Initial; - return S_OK; - } - - if (!reader->resume[XmlReadResume_Body]) - { - /* now at least a single space char should be there */ - if (!is_wchar_space(*ptr)) return WC_E_WHITESPACE; - reader_skipspaces(reader); - ptr = start = reader_get_cur(reader); - reader->resume[XmlReadResume_Body] = start; - } - else - { - start = reader->resume[XmlReadResume_Body]; - ptr = reader_get_cur(reader); - } - - while (*ptr) + start = reader->resume[XmlReadResume_Body]; + while (*(ptr = reader_get_ptr(reader))) { if (ptr[0] == '?') { if (ptr[1] == '>') { + UINT cur = reader_get_cur(reader); strval value; - TRACE("%s\n", debugstr_wn(start, ptr-start)); + /* strip all leading whitespace chars */ + while (start < cur) + { + ptr = reader_get_ptr2(reader, start); + if (!is_wchar_space(*ptr)) break; + start++; + } + + reader_init_strvalue(start, cur-start, &value); + /* skip '?>' */ reader_skipn(reader, 2); + TRACE("%s\n", debug_strval(reader, &value)); reader->nodetype = XmlNodeType_ProcessingInstruction; reader->resumestate = XmlReadResumeState_Initial; - reader->resume[XmlReadResume_Body] = NULL; - reader_init_strvalue(start, ptr-start, &value); + reader->resume[XmlReadResume_Body] = 0; reader_set_strvalue(reader, StringValue_Value, &value); return S_OK; } - else - { - ptr++; - reader_more(reader); - } - } - else - { - reader_skipn(reader, 1); - ptr = reader_get_cur(reader); } + + reader_skipn(reader, 1); + ptr = reader_get_ptr(reader); } return S_OK; @@ -1461,10 +1487,10 @@ static HRESULT reader_parse_whitespace(xmlreader *reader) WCHAR *start, *ptr; reader_shrink(reader); - start = reader_get_cur(reader); + start = reader_get_ptr(reader); reader_skipspaces(reader); - ptr = reader_get_cur(reader); + ptr = reader_get_ptr(reader); TRACE("%s\n", debugstr_wn(start, ptr-start)); reader->nodetype = XmlNodeType_Whitespace; @@ -1499,7 +1525,7 @@ static HRESULT reader_parse_misc(xmlreader *reader) while (1) { - const WCHAR *cur = reader_get_cur(reader); + const WCHAR *cur = reader_get_ptr(reader); if (is_wchar_space(*cur)) hr = reader_parse_whitespace(reader); @@ -1519,23 +1545,25 @@ static HRESULT reader_parse_misc(xmlreader *reader) /* [11] SystemLiteral ::= ('"' [^"]* '"') | ("'" [^']* "'") */ static HRESULT reader_parse_sys_literal(xmlreader *reader, strval *literal) { - WCHAR *start = reader_get_cur(reader), *cur, quote; + WCHAR *cur = reader_get_ptr(reader), quote; + UINT start; - if (*start != '"' && *start != '\'') return WC_E_QUOTE; + if (*cur != '"' && *cur != '\'') return WC_E_QUOTE; - quote = *start; + quote = *cur; reader_skipn(reader, 1); - cur = start = reader_get_cur(reader); + cur = reader_get_ptr(reader); + start = reader_get_cur(reader); while (is_char(*cur) && *cur != quote) { reader_skipn(reader, 1); - cur = reader_get_cur(reader); + cur = reader_get_ptr(reader); } + reader_init_strvalue(start, reader_get_cur(reader)-start, literal); if (*cur == quote) reader_skipn(reader, 1); - reader_init_strvalue(start, cur-start, literal); - TRACE("%s\n", debugstr_wn(start, cur-start)); + TRACE("%s\n", debug_strval(reader, literal)); return S_OK; } @@ -1543,22 +1571,24 @@ static HRESULT reader_parse_sys_literal(xmlreader *reader, strval *literal) [13] PubidChar ::= #x20 | #xD | #xA | [a-zA-Z0-9] | [-'()+,./:=?;!*#@$_%] */ static HRESULT reader_parse_pub_literal(xmlreader *reader, strval *literal) { - WCHAR *start = reader_get_cur(reader), *cur, quote; + WCHAR *cur = reader_get_ptr(reader), quote; + UINT start; - if (*start != '"' && *start != '\'') return WC_E_QUOTE; + if (*cur != '"' && *cur != '\'') return WC_E_QUOTE; - quote = *start; + quote = *cur; reader_skipn(reader, 1); - cur = start; + start = reader_get_cur(reader); + cur = reader_get_ptr(reader); while (is_pubchar(*cur) && *cur != quote) { reader_skipn(reader, 1); - cur = reader_get_cur(reader); + cur = reader_get_ptr(reader); } - reader_init_strvalue(start, cur-start, literal); - TRACE("%s\n", debugstr_wn(start, cur-start)); + reader_init_strvalue(start, reader_get_cur(reader)-start, literal); + TRACE("%s\n", debug_strval(reader, literal)); return S_OK; } @@ -1587,7 +1617,7 @@ static HRESULT reader_parse_externalid(xmlreader *reader) hr = reader_parse_pub_literal(reader, &pub); if (FAILED(hr)) return hr; - reader_init_strvalue(publicW, strlenW(publicW), &name); + reader_init_cstrvalue(publicW, strlenW(publicW), &name); return reader_add_attr(reader, &name, &pub); } } @@ -1603,7 +1633,7 @@ static HRESULT reader_parse_externalid(xmlreader *reader) hr = reader_parse_sys_literal(reader, &sys); if (FAILED(hr)) return hr; - reader_init_strvalue(systemW, strlenW(systemW), &name); + reader_init_cstrvalue(systemW, strlenW(systemW), &name); return reader_add_attr(reader, &name, &sys); } @@ -1639,7 +1669,7 @@ static HRESULT reader_parse_dtd(xmlreader *reader) reader_skipspaces(reader); - cur = reader_get_cur(reader); + cur = reader_get_ptr(reader); if (*cur != '>') { FIXME("internal subset parsing not implemented\n"); @@ -1659,22 +1689,24 @@ static HRESULT reader_parse_dtd(xmlreader *reader) /* [11 NS] LocalPart ::= NCName */ static HRESULT reader_parse_local(xmlreader *reader, strval *local) { - WCHAR *ptr, *start; + WCHAR *ptr; + UINT start; if (reader->resume[XmlReadResume_Local]) { start = reader->resume[XmlReadResume_Local]; - ptr = reader_get_cur(reader); + ptr = reader_get_ptr(reader); } else { - ptr = start = reader_get_cur(reader); + ptr = reader_get_ptr(reader); + start = reader_get_cur(reader); } while (is_ncnamechar(*ptr)) { reader_skipn(reader, 1); - ptr = reader_get_cur(reader); + ptr = reader_get_ptr(reader); } if (is_reader_pending(reader)) @@ -1683,9 +1715,9 @@ static HRESULT reader_parse_local(xmlreader *reader, strval *local) return E_PENDING; } else - reader->resume[XmlReadResume_Local] = NULL; + reader->resume[XmlReadResume_Local] = 0; - reader_init_strvalue(start, ptr-start, local); + reader_init_strvalue(start, reader_get_cur(reader)-start, local); return S_OK; } @@ -1696,17 +1728,19 @@ static HRESULT reader_parse_local(xmlreader *reader, strval *local) [10 NS] Prefix ::= NCName */ static HRESULT reader_parse_qname(xmlreader *reader, strval *prefix, strval *local, strval *qname) { - WCHAR *ptr, *start; + WCHAR *ptr; + UINT start; HRESULT hr; if (reader->resume[XmlReadResume_Name]) { start = reader->resume[XmlReadResume_Name]; - ptr = reader_get_cur(reader); + ptr = reader_get_ptr(reader); } else { - ptr = start = reader_get_cur(reader); + ptr = reader_get_ptr(reader); + start = reader_get_cur(reader); reader->resume[XmlReadResume_Name] = start; if (!is_ncnamechar(*ptr)) return NC_E_QNAMECHARACTER; } @@ -1726,7 +1760,7 @@ static HRESULT reader_parse_qname(xmlreader *reader, strval *prefix, strval *loc while (is_ncnamechar(*ptr)) { reader_skipn(reader, 1); - ptr = reader_get_cur(reader); + ptr = reader_get_ptr(reader); } if (is_reader_pending(reader)) return E_PENDING; @@ -1734,7 +1768,7 @@ static HRESULT reader_parse_qname(xmlreader *reader, strval *prefix, strval *loc /* got a qualified name */ if (*ptr == ':') { - reader_init_strvalue(start, ptr-start, prefix); + reader_init_strvalue(start, reader_get_cur(reader)-start, prefix); /* skip ':' */ reader_skipn(reader, 1); @@ -1743,25 +1777,25 @@ static HRESULT reader_parse_qname(xmlreader *reader, strval *prefix, strval *loc } else { - reader_init_strvalue(reader->resume[XmlReadResume_Name], ptr-reader->resume[XmlReadResume_Name], local); - reader_init_strvalue(NULL, 0, prefix); + reader_init_strvalue(reader->resume[XmlReadResume_Name], reader_get_cur(reader)-reader->resume[XmlReadResume_Name], local); + reader_init_strvalue(0, 0, prefix); } } - reader_init_strvalue(start, ptr-start, local); + reader_init_strvalue(start, reader_get_cur(reader)-start, local); if (prefix->len) - TRACE("qname %s:%s\n", debugstr_wn(prefix->start, prefix->len), debugstr_wn(local->start, local->len)); + TRACE("qname %s:%s\n", debug_strval(reader, prefix), debug_strval(reader, local)); else - TRACE("ncname %s\n", debugstr_wn(local->start, local->len)); + TRACE("ncname %s\n", debug_strval(reader, local)); - reader_init_strvalue(prefix->start ? prefix->start : local->start, + reader_init_strvalue(prefix->len ? prefix->start : local->start, /* count ':' too */ (prefix->len ? prefix->len + 1 : 0) + local->len, qname); - reader->resume[XmlReadResume_Name] = NULL; - reader->resume[XmlReadResume_Local] = NULL; + reader->resume[XmlReadResume_Name] = 0; + reader->resume[XmlReadResume_Local] = 0; return S_OK; } @@ -1788,36 +1822,36 @@ static void reader_normalize_space(xmlreader *reader, WCHAR *ptr) *ptr = ' '; } -static WCHAR get_predefined_entity(const strval *name) +static WCHAR get_predefined_entity(const xmlreader *reader, const strval *name) { static const WCHAR entltW[] = {'l','t'}; static const WCHAR entgtW[] = {'g','t'}; static const WCHAR entampW[] = {'a','m','p'}; static const WCHAR entaposW[] = {'a','p','o','s'}; static const WCHAR entquotW[] = {'q','u','o','t'}; - static const strval lt = { (WCHAR*)entltW, 2 }; static const strval gt = { (WCHAR*)entgtW, 2 }; static const strval amp = { (WCHAR*)entampW, 3 }; static const strval apos = { (WCHAR*)entaposW, 4 }; static const strval quot = { (WCHAR*)entquotW, 4 }; + WCHAR *str = reader_get_strptr(reader, name); - switch (name->str[0]) + switch (*str) { case 'l': - if (strval_eq(name, <)) return '<'; + if (strval_eq(reader, name, <)) return '<'; break; case 'g': - if (strval_eq(name, >)) return '>'; + if (strval_eq(reader, name, >)) return '>'; break; case 'a': - if (strval_eq(name, &)) + if (strval_eq(reader, name, &)) return '&'; - else if (strval_eq(name, &apos)) + else if (strval_eq(reader, name, &apos)) return '\''; break; case 'q': - if (strval_eq(name, ")) return '\"'; + if (strval_eq(reader, name, ")) return '\"'; break; default: ; @@ -1832,24 +1866,25 @@ static WCHAR get_predefined_entity(const strval *name) static HRESULT reader_parse_reference(xmlreader *reader) { encoded_buffer *buffer = &reader->input->buffer->utf16; - WCHAR *start = reader_get_cur(reader), *ptr; + WCHAR *start = reader_get_ptr(reader), *ptr; + UINT cur = reader_get_cur(reader); WCHAR ch = 0; int len; /* skip '&' */ reader_skipn(reader, 1); - ptr = reader_get_cur(reader); + ptr = reader_get_ptr(reader); if (*ptr == '#') { reader_skipn(reader, 1); - ptr = reader_get_cur(reader); + ptr = reader_get_ptr(reader); /* hex char or decimal */ if (*ptr == 'x') { reader_skipn(reader, 1); - ptr = reader_get_cur(reader); + ptr = reader_get_ptr(reader); while (*ptr != ';') { @@ -1862,7 +1897,7 @@ static HRESULT reader_parse_reference(xmlreader *reader) else return ch ? WC_E_SEMICOLON : WC_E_HEXDIGIT; reader_skipn(reader, 1); - ptr = reader_get_cur(reader); + ptr = reader_get_ptr(reader); } } else @@ -1873,7 +1908,7 @@ static HRESULT reader_parse_reference(xmlreader *reader) { ch = ch*10 + *ptr - '0'; reader_skipn(reader, 1); - ptr = reader_get_cur(reader); + ptr = reader_get_ptr(reader); } else return ch ? WC_E_SEMICOLON : WC_E_DIGIT; @@ -1887,7 +1922,7 @@ static HRESULT reader_parse_reference(xmlreader *reader) len = buffer->written - ((char*)ptr - buffer->data) - sizeof(WCHAR); memmove(start+1, ptr+1, len); - buffer->cur = (char*)(start+1); + buffer->cur = cur + 1; *start = ch; } @@ -1899,22 +1934,22 @@ static HRESULT reader_parse_reference(xmlreader *reader) hr = reader_parse_name(reader, &name); if (FAILED(hr)) return hr; - ptr = reader_get_cur(reader); + ptr = reader_get_ptr(reader); if (*ptr != ';') return WC_E_SEMICOLON; /* predefined entities resolve to a single character */ - ch = get_predefined_entity(&name); + ch = get_predefined_entity(reader, &name); if (ch) { len = buffer->written - ((char*)ptr - buffer->data) - sizeof(WCHAR); memmove(start+1, ptr+1, len); - buffer->cur = (char*)(start+1); + buffer->cur = cur + 1; *start = ch; } else { - FIXME("undeclared entity %s\n", debugstr_wn(name.str, name.len)); + FIXME("undeclared entity %s\n", debug_strval(reader, &name)); return WC_E_UNDECLAREDENTITY; } @@ -1926,26 +1961,28 @@ static HRESULT reader_parse_reference(xmlreader *reader) /* [10 NS] AttValue ::= '"' ([^<&"] | Reference)* '"' | "'" ([^<&'] | Reference)* "'" */ static HRESULT reader_parse_attvalue(xmlreader *reader, strval *value) { - WCHAR *ptr, *start; - WCHAR quote; + WCHAR *ptr, quote; + UINT start; - ptr = reader_get_cur(reader); + ptr = reader_get_ptr(reader); /* skip opening quote */ quote = *ptr; if (quote != '\"' && quote != '\'') return WC_E_QUOTE; reader_skipn(reader, 1); - start = ptr = reader_get_cur(reader); + ptr = reader_get_ptr(reader); + start = reader_get_cur(reader); while (*ptr) { if (*ptr == '<') return WC_E_LESSTHAN; if (*ptr == quote) { + reader_init_strvalue(start, reader_get_cur(reader)-start, value); /* skip closing quote */ reader_skipn(reader, 1); - break; + return S_OK; } if (*ptr == '&') @@ -1958,12 +1995,10 @@ static HRESULT reader_parse_attvalue(xmlreader *reader, strval *value) reader_normalize_space(reader, ptr); reader_skipn(reader, 1); } - ptr = reader_get_cur(reader); + ptr = reader_get_ptr(reader); } - reader_init_strvalue(start, ptr-start, value); - - return S_OK; + return WC_E_QUOTE; } /* [1 NS] NSAttName ::= PrefixedAttName | DefaultAttName @@ -1979,15 +2014,15 @@ static HRESULT reader_parse_attribute(xmlreader *reader) hr = reader_parse_qname(reader, &prefix, &local, &qname); if (FAILED(hr)) return hr; - reader_init_strvalue((WCHAR*)xmlnsW, 5, &xmlns); + reader_init_cstrvalue((WCHAR*)xmlnsW, 5, &xmlns); - if (strval_eq(&prefix, &xmlns)) + if (strval_eq(reader, &prefix, &xmlns)) { FIXME("namespace definitions not supported\n"); return E_NOTIMPL; } - if (strval_eq(&qname, &xmlns)) + if (strval_eq(reader, &qname, &xmlns)) { FIXME("default namespace definitions not supported\n"); return E_NOTIMPL; @@ -1999,7 +2034,7 @@ static HRESULT reader_parse_attribute(xmlreader *reader) hr = reader_parse_attvalue(reader, &value); if (FAILED(hr)) return hr; - TRACE("%s=%s\n", debugstr_wn(local.str, local.len), debugstr_wn(value.str, value.len)); + TRACE("%s=%s\n", debug_strval(reader, &local), debug_strval(reader, &value)); return reader_add_attr(reader, &local, &value); } @@ -2114,7 +2149,7 @@ static HRESULT reader_parse_endtag(xmlreader *reader) /* Element stack should never be empty at this point, cause we shouldn't get to content parsing if it's empty. */ elem = LIST_ENTRY(list_head(&reader->elements), struct element, entry); - if (!strval_eq(&elem->qname, &qname)) return WC_E_ELEMENTMATCH; + if (!strval_eq(reader, &elem->qname, &qname)) return WC_E_ELEMENTMATCH; reader_pop_element(reader); @@ -2135,19 +2170,21 @@ static HRESULT reader_parse_endtag(xmlreader *reader) [21] CDEnd ::= ']]>' */ static HRESULT reader_parse_cdata(xmlreader *reader) { - WCHAR *start, *ptr; + WCHAR *ptr; + UINT start; - if (reader->resume[XmlReadResume_Body]) + if (reader->resumestate == XmlReadResumeState_CDATA) { start = reader->resume[XmlReadResume_Body]; - ptr = reader_get_cur(reader); + ptr = reader_get_ptr(reader); } else { /* skip markup 'nodetype = XmlNodeType_CDATA; reader->resume[XmlReadResume_Body] = start; reader->resumestate = XmlReadResumeState_CDATA; @@ -2162,14 +2199,16 @@ static HRESULT reader_parse_cdata(xmlreader *reader) { strval value; - TRACE("%s\n", debugstr_wn(start, ptr-start)); + reader_init_strvalue(start, reader_get_cur(reader)-start, &value); + /* skip ']]>' */ reader_skipn(reader, 3); - reader_init_strvalue(start, ptr-start, &value); + TRACE("%s\n", debug_strval(reader, &value)); + reader_set_strvalue(reader, StringValue_LocalName, &strval_empty); reader_set_strvalue(reader, StringValue_QualifiedName, &strval_empty); reader_set_strvalue(reader, StringValue_Value, &value); - reader->resume[XmlReadResume_Body] = NULL; + reader->resume[XmlReadResume_Body] = 0; reader->resumestate = XmlReadResumeState_Initial; return S_OK; } @@ -2192,17 +2231,19 @@ static HRESULT reader_parse_cdata(xmlreader *reader) /* [14] CharData ::= [^<&]* - ([^<&]* ']]>' [^<&]*) */ static HRESULT reader_parse_chardata(xmlreader *reader) { - WCHAR *start, *ptr; + WCHAR *ptr; + UINT start; - if (reader->resume[XmlReadResume_Body]) + if (reader->resumestate == XmlReadResumeState_CharData) { start = reader->resume[XmlReadResume_Body]; - ptr = reader_get_cur(reader); + ptr = reader_get_ptr(reader); } else { reader_shrink(reader); - ptr = start = reader_get_cur(reader); + ptr = reader_get_ptr(reader); + start = reader_get_cur(reader); /* There's no text */ if (!*ptr || *ptr == '<') return S_OK; reader->nodetype = is_wchar_space(*ptr) ? XmlNodeType_Whitespace : XmlNodeType_Text; @@ -2224,9 +2265,9 @@ static HRESULT reader_parse_chardata(xmlreader *reader) { strval value; - reader_init_strvalue(start, ptr-start, &value); + reader_init_strvalue(start, reader_get_cur(reader)-start, &value); reader_set_strvalue(reader, StringValue_Value, &value); - reader->resume[XmlReadResume_Body] = NULL; + reader->resume[XmlReadResume_Body] = 0; reader->resumestate = XmlReadResumeState_Initial; return S_OK; } @@ -2697,10 +2738,11 @@ static HRESULT WINAPI xmlreader_GetValue(IXmlReader* iface, const WCHAR **value, if (!val->str) { - val->str = reader_alloc(reader, (val->len+1)*sizeof(WCHAR)); - if (!val->str) return E_OUTOFMEMORY; - memcpy(val->str, val->start, val->len*sizeof(WCHAR)); - val->str[val->len] = 0; + WCHAR *ptr = reader_alloc(reader, (val->len+1)*sizeof(WCHAR)); + if (!ptr) return E_OUTOFMEMORY; + memcpy(ptr, reader_get_strptr(reader, val), val->len*sizeof(WCHAR)); + ptr[val->len] = 0; + val->str = ptr; } *value = val->str; @@ -2722,7 +2764,7 @@ static HRESULT WINAPI xmlreader_ReadValueChunk(IXmlReader* iface, WCHAR *buffer, if (val->len) { len = min(chunk_size, val->len); - memcpy(buffer, val->start, len); + memcpy(buffer, reader_get_ptr2(reader, val->start), len); val->start += len; val->len -= len; if (read) *read = len; diff --git a/dlls/xmllite/tests/reader.c b/dlls/xmllite/tests/reader.c index 6296028..5c4f2a6 100644 --- a/dlls/xmllite/tests/reader.c +++ b/dlls/xmllite/tests/reader.c @@ -855,6 +855,7 @@ static struct test_entry pi_tests[] = { { "", "pi", "", S_OK }, { "", "pi", "pi data", S_OK }, { "", "pi", "pi data ", S_OK }, + { "", "pi", "data ", S_OK }, { "", NULL, NULL, NC_E_NAMECOLON, WC_E_NAMECHARACTER }, { "", NULL, NULL, WC_E_PI, WC_E_NAMECHARACTER }, { "", NULL, NULL, WC_E_PI, WC_E_NAMECHARACTER }, -- 1.7.10.4