xmllite/writer: Implement WriteDocType().
Signed-off-by: Nikolay Sivov <nsivov@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
eff5223ae3
commit
4c779c07bd
|
@ -95,7 +95,7 @@ static const WCHAR gtW[] = {'>',0};
|
|||
static const WCHAR commentW[] = {'<','!','-','-',0};
|
||||
static const WCHAR piW[] = {'<','?',0};
|
||||
|
||||
static BOOL is_namestartchar(WCHAR ch);
|
||||
BOOL is_namestartchar(WCHAR ch);
|
||||
|
||||
static const char *debugstr_nodetype(XmlNodeType nodetype)
|
||||
{
|
||||
|
@ -1491,7 +1491,7 @@ static inline BOOL is_char(WCHAR ch)
|
|||
}
|
||||
|
||||
/* [13] PubidChar ::= #x20 | #xD | #xA | [a-zA-Z0-9] | [-'()+,./:=?;!*#@$_%] */
|
||||
static inline BOOL is_pubchar(WCHAR ch)
|
||||
BOOL is_pubchar(WCHAR ch)
|
||||
{
|
||||
return (ch == ' ') ||
|
||||
(ch >= 'a' && ch <= 'z') ||
|
||||
|
@ -1504,7 +1504,7 @@ static inline BOOL is_pubchar(WCHAR ch)
|
|||
(ch == '_') || (ch == '\r') || (ch == '\n');
|
||||
}
|
||||
|
||||
static inline BOOL is_namestartchar(WCHAR ch)
|
||||
BOOL is_namestartchar(WCHAR ch)
|
||||
{
|
||||
return (ch == ':') || (ch >= 'A' && ch <= 'Z') ||
|
||||
(ch == '_') || (ch >= 'a' && ch <= 'z') ||
|
||||
|
@ -1548,7 +1548,7 @@ BOOL is_ncnamechar(WCHAR ch)
|
|||
(ch >= 0xfdf0 && ch <= 0xfffd);
|
||||
}
|
||||
|
||||
static inline BOOL is_namechar(WCHAR ch)
|
||||
BOOL is_namechar(WCHAR ch)
|
||||
{
|
||||
return (ch == ':') || is_ncnamechar(ch);
|
||||
}
|
||||
|
|
|
@ -135,7 +135,8 @@ static void check_writer_state(IXmlWriter *writer, HRESULT exp_hr)
|
|||
hr = IXmlWriter_WriteComment(writer, aW);
|
||||
ok(hr == exp_hr, "got 0x%08x, expected 0x%08x\n", hr, exp_hr);
|
||||
|
||||
/* FIXME: add WriteDocType */
|
||||
hr = IXmlWriter_WriteDocType(writer, aW, NULL, NULL, NULL);
|
||||
ok(hr == exp_hr, "got 0x%08x, expected 0x%08x\n", hr, exp_hr);
|
||||
|
||||
hr = IXmlWriter_WriteElementString(writer, NULL, aW, NULL, aW);
|
||||
ok(hr == exp_hr, "got 0x%08x, expected 0x%08x\n", hr, exp_hr);
|
||||
|
@ -353,7 +354,8 @@ static void test_invalid_output_encoding(IXmlWriter *writer, IUnknown *output)
|
|||
hr = IXmlWriter_WriteComment(writer, aW);
|
||||
ok(hr == MX_E_ENCODING, "Unexpected hr %#x.\n", hr);
|
||||
|
||||
/* TODO: WriteDocType */
|
||||
hr = IXmlWriter_WriteDocType(writer, aW, NULL, NULL, NULL);
|
||||
ok(hr == MX_E_ENCODING, "Unexpected hr %#x.\n", hr);
|
||||
|
||||
hr = IXmlWriter_WriteElementString(writer, NULL, aW, NULL, NULL);
|
||||
ok(hr == MX_E_ENCODING, "Unexpected hr %#x.\n", hr);
|
||||
|
@ -2113,6 +2115,109 @@ static void test_WriteString(void)
|
|||
IStream_Release(stream);
|
||||
}
|
||||
|
||||
static HRESULT write_doctype(IXmlWriter *writer, const char *name, const char *pubid, const char *sysid,
|
||||
const char *subset)
|
||||
{
|
||||
WCHAR *nameW, *pubidW, *sysidW, *subsetW;
|
||||
HRESULT hr;
|
||||
|
||||
nameW = strdupAtoW(name);
|
||||
pubidW = strdupAtoW(pubid);
|
||||
sysidW = strdupAtoW(sysid);
|
||||
subsetW = strdupAtoW(subset);
|
||||
|
||||
hr = IXmlWriter_WriteDocType(writer, nameW, pubidW, sysidW, subsetW);
|
||||
|
||||
heap_free(nameW);
|
||||
heap_free(pubidW);
|
||||
heap_free(sysidW);
|
||||
heap_free(subsetW);
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
static void test_WriteDocType(void)
|
||||
{
|
||||
static const struct
|
||||
{
|
||||
const char *name;
|
||||
const char *pubid;
|
||||
const char *sysid;
|
||||
const char *subset;
|
||||
const char *output;
|
||||
}
|
||||
doctype_tests[] =
|
||||
{
|
||||
{ "a", "", NULL, NULL, "<!DOCTYPE a PUBLIC \"\" \"\">" },
|
||||
{ "a", NULL, NULL, NULL, "<!DOCTYPE a>" },
|
||||
{ "a", NULL, "", NULL, "<!DOCTYPE a SYSTEM \"\">" },
|
||||
{ "a", "", "", NULL, "<!DOCTYPE a PUBLIC \"\" \"\">" },
|
||||
{ "a", "pubid", "", NULL, "<!DOCTYPE a PUBLIC \"pubid\" \"\">" },
|
||||
{ "a", "pubid", NULL, NULL, "<!DOCTYPE a PUBLIC \"pubid\" \"\">" },
|
||||
{ "a", "", "sysid", NULL, "<!DOCTYPE a PUBLIC \"\" \"sysid\">" },
|
||||
{ "a", NULL, NULL, "", "<!DOCTYPE a []>" },
|
||||
{ "a", NULL, NULL, "subset", "<!DOCTYPE a [subset]>" },
|
||||
{ "a", "", NULL, "subset", "<!DOCTYPE a PUBLIC \"\" \"\" [subset]>" },
|
||||
{ "a", NULL, "", "subset", "<!DOCTYPE a SYSTEM \"\" [subset]>" },
|
||||
{ "a", "", "", "subset", "<!DOCTYPE a PUBLIC \"\" \"\" [subset]>" },
|
||||
{ "a", "pubid", NULL, "subset", "<!DOCTYPE a PUBLIC \"pubid\" \"\" [subset]>" },
|
||||
{ "a", "pubid", "", "subset", "<!DOCTYPE a PUBLIC \"pubid\" \"\" [subset]>" },
|
||||
{ "a", NULL, "sysid", "subset", "<!DOCTYPE a SYSTEM \"sysid\" [subset]>" },
|
||||
{ "a", "", "sysid", "subset", "<!DOCTYPE a PUBLIC \"\" \"sysid\" [subset]>" },
|
||||
{ "a", "pubid", "sysid", "subset", "<!DOCTYPE a PUBLIC \"pubid\" \"sysid\" [subset]>" },
|
||||
};
|
||||
static const WCHAR pubidW[] = {'p',0x100,'i','d',0};
|
||||
static const WCHAR nameW[] = {'-','a',0};
|
||||
static const WCHAR emptyW[] = { 0 };
|
||||
IXmlWriter *writer;
|
||||
IStream *stream;
|
||||
unsigned int i;
|
||||
HRESULT hr;
|
||||
|
||||
hr = CreateXmlWriter(&IID_IXmlWriter, (void **)&writer, NULL);
|
||||
ok(hr == S_OK, "Failed to create writer instance, hr %#x.\n", hr);
|
||||
|
||||
stream = writer_set_output(writer);
|
||||
|
||||
hr = IXmlWriter_WriteDocType(writer, NULL, NULL, NULL, NULL);
|
||||
ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
|
||||
|
||||
hr = IXmlWriter_WriteDocType(writer, emptyW, NULL, NULL, NULL);
|
||||
ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
|
||||
|
||||
/* Name validation. */
|
||||
hr = IXmlWriter_WriteDocType(writer, nameW, NULL, NULL, NULL);
|
||||
ok(hr == WC_E_NAMECHARACTER, "Unexpected hr %#x.\n", hr);
|
||||
|
||||
/* Pubid validation. */
|
||||
hr = IXmlWriter_WriteDocType(writer, aW, pubidW, NULL, NULL);
|
||||
ok(hr == WC_E_PUBLICID, "Unexpected hr %#x.\n", hr);
|
||||
|
||||
IStream_Release(stream);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(doctype_tests); i++)
|
||||
{
|
||||
stream = writer_set_output(writer);
|
||||
|
||||
hr = write_doctype(writer, doctype_tests[i].name, doctype_tests[i].pubid, doctype_tests[i].sysid,
|
||||
doctype_tests[i].subset);
|
||||
ok(hr == S_OK, "%u: failed to write doctype, hr %#x.\n", i, hr);
|
||||
|
||||
hr = IXmlWriter_Flush(writer);
|
||||
ok(hr == S_OK, "Failed to flush, hr %#x.\n", hr);
|
||||
|
||||
CHECK_OUTPUT(stream, doctype_tests[i].output);
|
||||
|
||||
hr = write_doctype(writer, doctype_tests[i].name, doctype_tests[i].pubid, doctype_tests[i].sysid,
|
||||
doctype_tests[i].subset);
|
||||
ok(hr == WR_E_INVALIDACTION, "Unexpected hr %#x.\n", hr);
|
||||
|
||||
IStream_Release(stream);
|
||||
}
|
||||
|
||||
IXmlWriter_Release(writer);
|
||||
}
|
||||
|
||||
START_TEST(writer)
|
||||
{
|
||||
test_writer_create();
|
||||
|
@ -2134,4 +2239,5 @@ START_TEST(writer)
|
|||
test_WriteFullEndElement();
|
||||
test_WriteCharEntity();
|
||||
test_WriteString();
|
||||
test_WriteDocType();
|
||||
}
|
||||
|
|
|
@ -366,6 +366,50 @@ static HRESULT is_valid_ncname(const WCHAR *str, int *out)
|
|||
return S_OK;
|
||||
}
|
||||
|
||||
static HRESULT is_valid_name(const WCHAR *str, unsigned int *out)
|
||||
{
|
||||
unsigned int len = 1;
|
||||
|
||||
*out = 0;
|
||||
|
||||
if (!str || !*str)
|
||||
return S_OK;
|
||||
|
||||
if (!is_namestartchar(*str++))
|
||||
return WC_E_NAMECHARACTER;
|
||||
|
||||
while (*str++)
|
||||
{
|
||||
if (!is_namechar(*str))
|
||||
return WC_E_NAMECHARACTER;
|
||||
len++;
|
||||
}
|
||||
|
||||
*out = len;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static HRESULT is_valid_pubid(const WCHAR *str, unsigned int *out)
|
||||
{
|
||||
unsigned int len = 0;
|
||||
|
||||
*out = 0;
|
||||
|
||||
if (!str || !*str)
|
||||
return S_OK;
|
||||
|
||||
while (*str)
|
||||
{
|
||||
if (!is_pubchar(*str++))
|
||||
return WC_E_PUBLICID;
|
||||
len++;
|
||||
}
|
||||
|
||||
*out = len;
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static HRESULT init_output_buffer(xmlwriteroutput *output)
|
||||
{
|
||||
struct output_buffer *buffer = &output->buffer;
|
||||
|
@ -457,6 +501,11 @@ static HRESULT write_output_buffer_quoted(xmlwriteroutput *output, const WCHAR *
|
|||
return S_OK;
|
||||
}
|
||||
|
||||
static HRESULT write_output_buffer_char(xmlwriteroutput *output, WCHAR ch)
|
||||
{
|
||||
return write_output_buffer(output, &ch, 1);
|
||||
}
|
||||
|
||||
/* TODO: test if we need to validate char range */
|
||||
static HRESULT write_output_qname(xmlwriteroutput *output, const WCHAR *prefix, int prefix_len,
|
||||
const WCHAR *local_name, int local_len)
|
||||
|
@ -1103,15 +1152,69 @@ static HRESULT WINAPI xmlwriter_WriteComment(IXmlWriter *iface, LPCWSTR comment)
|
|||
return S_OK;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI xmlwriter_WriteDocType(IXmlWriter *iface, LPCWSTR pwszName, LPCWSTR pwszPublicId,
|
||||
LPCWSTR pwszSystemId, LPCWSTR pwszSubset)
|
||||
static HRESULT WINAPI xmlwriter_WriteDocType(IXmlWriter *iface, LPCWSTR name, LPCWSTR pubid,
|
||||
LPCWSTR sysid, LPCWSTR subset)
|
||||
{
|
||||
static const WCHAR doctypeW[] = {'<','!','D','O','C','T','Y','P','E',' '};
|
||||
static const WCHAR publicW[] = {' ','P','U','B','L','I','C',' '};
|
||||
static const WCHAR systemW[] = {' ','S','Y','S','T','E','M',' '};
|
||||
xmlwriter *This = impl_from_IXmlWriter(iface);
|
||||
unsigned int name_len, pubid_len;
|
||||
HRESULT hr;
|
||||
|
||||
FIXME("%p %s %s %s %s\n", This, wine_dbgstr_w(pwszName), wine_dbgstr_w(pwszPublicId),
|
||||
wine_dbgstr_w(pwszSystemId), wine_dbgstr_w(pwszSubset));
|
||||
TRACE("(%p)->(%s %s %s %s)\n", This, wine_dbgstr_w(name), wine_dbgstr_w(pubid), wine_dbgstr_w(sysid),
|
||||
wine_dbgstr_w(subset));
|
||||
|
||||
return E_NOTIMPL;
|
||||
switch (This->state)
|
||||
{
|
||||
case XmlWriterState_Initial:
|
||||
return E_UNEXPECTED;
|
||||
case XmlWriterState_InvalidEncoding:
|
||||
return MX_E_ENCODING;
|
||||
case XmlWriterState_Content:
|
||||
case XmlWriterState_DocClosed:
|
||||
return WR_E_INVALIDACTION;
|
||||
default:
|
||||
;
|
||||
}
|
||||
|
||||
if (is_empty_string(name))
|
||||
return E_INVALIDARG;
|
||||
|
||||
if (FAILED(hr = is_valid_name(name, &name_len)))
|
||||
return hr;
|
||||
|
||||
if (FAILED(hr = is_valid_pubid(pubid, &pubid_len)))
|
||||
return hr;
|
||||
|
||||
write_output_buffer(This->output, doctypeW, ARRAY_SIZE(doctypeW));
|
||||
write_output_buffer(This->output, name, name_len);
|
||||
|
||||
if (pubid)
|
||||
{
|
||||
write_output_buffer(This->output, publicW, ARRAY_SIZE(publicW));
|
||||
write_output_buffer_quoted(This->output, pubid, pubid_len);
|
||||
write_output_buffer(This->output, spaceW, ARRAY_SIZE(spaceW));
|
||||
write_output_buffer_quoted(This->output, sysid, -1);
|
||||
}
|
||||
else if (sysid)
|
||||
{
|
||||
write_output_buffer(This->output, systemW, ARRAY_SIZE(systemW));
|
||||
write_output_buffer_quoted(This->output, sysid, -1);
|
||||
}
|
||||
|
||||
if (subset)
|
||||
{
|
||||
write_output_buffer_char(This->output, ' ');
|
||||
write_output_buffer_char(This->output, '[');
|
||||
write_output_buffer(This->output, subset, -1);
|
||||
write_output_buffer_char(This->output, ']');
|
||||
}
|
||||
write_output_buffer_char(This->output, '>');
|
||||
|
||||
This->state = XmlWriterState_Content;
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI xmlwriter_WriteElementString(IXmlWriter *iface, LPCWSTR prefix,
|
||||
|
|
|
@ -61,5 +61,8 @@ const WCHAR *get_encoding_name(xml_encoding) DECLSPEC_HIDDEN;
|
|||
xml_encoding get_encoding_from_codepage(UINT) DECLSPEC_HIDDEN;
|
||||
|
||||
BOOL is_ncnamechar(WCHAR ch) DECLSPEC_HIDDEN;
|
||||
BOOL is_pubchar(WCHAR ch) DECLSPEC_HIDDEN;
|
||||
BOOL is_namestartchar(WCHAR ch) DECLSPEC_HIDDEN;
|
||||
BOOL is_namechar(WCHAR ch) DECLSPEC_HIDDEN;
|
||||
|
||||
#endif /* __XMLLITE_PRIVATE__ */
|
||||
|
|
Loading…
Reference in New Issue