Merge branch 'master' into compact
This commit is contained in:
commit
f81d7cc018
17 changed files with 230 additions and 51 deletions
2
Makefile
2
Makefile
|
@ -30,7 +30,7 @@ all: $(EXECUTABLE)
|
|||
|
||||
ifeq ($(config),coverage)
|
||||
test: $(EXECUTABLE)
|
||||
@find $(BUILD) -name '*.gcda' | xargs -r rm
|
||||
-@find $(BUILD) -name '*.gcda' | xargs rm
|
||||
./$(EXECUTABLE)
|
||||
@gcov -b -c $(BUILD)/src/pugixml.cpp.gcda | sed -e '/./{H;$!d;}' -e 'x;/pugixml.cpp/!d;'
|
||||
@ls *.gcov | grep -v pugixml.cpp.gcov | xargs rm
|
||||
|
|
|
@ -30,11 +30,11 @@ This is the complete manual for pugixml, which describes all features of the lib
|
|||
|
||||
[section:feedback Feedback]
|
||||
|
||||
If you believe you've found a bug in pugixml (bugs include compilation problems (errors/warnings), crashes, performance degradation and incorrect behavior), please file an issue via [@http://code.google.com/p/pugixml/issues/entry issue submission form]. Be sure to include the relevant information so that the bug can be reproduced: the version of pugixml, compiler version and target architecture, the code that uses pugixml and exhibits the bug, etc.
|
||||
If you believe you've found a bug in pugixml (bugs include compilation problems (errors/warnings), crashes, performance degradation and incorrect behavior), please file an issue via [@https://github.com/zeux/pugixml/issues/new issue submission form]. Be sure to include the relevant information so that the bug can be reproduced: the version of pugixml, compiler version and target architecture, the code that uses pugixml and exhibits the bug, etc.
|
||||
|
||||
Feature requests can be reported the same way as bugs, so if you're missing some functionality in pugixml or if the API is rough in some places and you can suggest an improvement, [@http://code.google.com/p/pugixml/issues/entry?template=Feature%20request file an issue]. However please note that there are many factors when considering API changes (compatibility with previous versions, API redundancy, etc.), so generally features that can be implemented via a small function without pugixml modification are not accepted. However, all rules have exceptions.
|
||||
Feature requests can be reported the same way as bugs, so if you're missing some functionality in pugixml or if the API is rough in some places and you can suggest an improvement, [@https://github.com/zeux/pugixml/issues/new file an issue]. However please note that there are many factors when considering API changes (compatibility with previous versions, API redundancy, etc.), so generally features that can be implemented via a small function without pugixml modification are not accepted. However, all rules have exceptions.
|
||||
|
||||
If you have a contribution to pugixml, such as build script for some build system/IDE, or a well-designed set of helper functions, or a binding to some language other than C++, please [@http://code.google.com/p/pugixml/issues/entry?template=Feature%20request file an issue]. You can include the relevant patches as issue attachments. Your contribution has to be distributed under the terms of a license that's compatible with pugixml license; i.e. GPL/LGPL licensed code is not accepted.
|
||||
If you have a contribution to pugixml, such as build script for some build system/IDE, or a well-designed set of helper functions, or a binding to some language other than C++, please [@https://github.com/zeux/pugixml/issues/new file an issue]. You can include the relevant patches as issue attachments. Your contribution has to be distributed under the terms of a license that's compatible with pugixml license; i.e. GPL/LGPL licensed code is not accepted.
|
||||
|
||||
[#email]
|
||||
If filing an issue is not possible due to privacy or other concerns, you can contact pugixml author by e-mail directly: [@mailto:arseny.kapoulkine@gmail.com arseny.kapoulkine@gmail.com].
|
||||
|
|
|
@ -219,7 +219,7 @@ While the previously described functions save the whole document to the destinat
|
|||
|
||||
[section:feedback Feedback]
|
||||
|
||||
If you believe you've found a bug in pugixml, please file an issue via [@http://code.google.com/p/pugixml/issues/entry issue submission form]. Be sure to include the relevant information so that the bug can be reproduced: the version of pugixml, compiler version and target architecture, the code that uses pugixml and exhibits the bug, etc. Feature requests and contributions can be filed as issues, too.
|
||||
If you believe you've found a bug in pugixml, please file an issue via [@https://github.com/zeux/pugixml/issues/new issue submission form]. Be sure to include the relevant information so that the bug can be reproduced: the version of pugixml, compiler version and target architecture, the code that uses pugixml and exhibits the bug, etc. Feature requests and contributions can be filed as issues, too.
|
||||
|
||||
[#email]
|
||||
If filing an issue is not possible due to privacy or other concerns, you can contact pugixml author by e-mail directly: [@mailto:arseny.kapoulkine@gmail.com arseny.kapoulkine@gmail.com].
|
||||
|
|
|
@ -11,7 +11,7 @@ struct xml_string_writer: pugi::xml_writer
|
|||
|
||||
virtual void write(const void* data, size_t size)
|
||||
{
|
||||
result += std::string(static_cast<const char*>(data), size);
|
||||
result.append(static_cast<const char*>(data), size);
|
||||
}
|
||||
};
|
||||
//]
|
||||
|
|
112
src/pugixml.cpp
112
src/pugixml.cpp
|
@ -559,7 +559,9 @@ PUGI__NS_BEGIN
|
|||
|
||||
char_t* allocate_string(size_t length)
|
||||
{
|
||||
PUGI__STATIC_ASSERT(xml_memory_page_size <= (1 << 16));
|
||||
static const size_t max_encoded_offset = (1 << 16) * sizeof(void*);
|
||||
|
||||
PUGI__STATIC_ASSERT(xml_memory_page_size <= max_encoded_offset);
|
||||
|
||||
// allocate memory for string and header block
|
||||
size_t size = sizeof(xml_memory_string_header) + length * sizeof(char_t);
|
||||
|
@ -575,12 +577,14 @@ PUGI__NS_BEGIN
|
|||
// setup header
|
||||
ptrdiff_t page_offset = reinterpret_cast<char*>(header) - reinterpret_cast<char*>(page) - sizeof(xml_memory_page);
|
||||
|
||||
assert(page_offset >= 0 && page_offset < (1 << 16));
|
||||
header->page_offset = static_cast<uint16_t>(page_offset);
|
||||
assert(page_offset % sizeof(void*) == 0);
|
||||
assert(page_offset >= 0 && static_cast<size_t>(page_offset) < max_encoded_offset);
|
||||
header->page_offset = static_cast<uint16_t>(static_cast<size_t>(page_offset) / sizeof(void*));
|
||||
|
||||
// full_size == 0 for large strings that occupy the whole page
|
||||
assert(full_size < (1 << 16) || (page->busy_size == full_size && page_offset == 0));
|
||||
header->full_size = static_cast<uint16_t>(full_size < (1 << 16) ? full_size : 0);
|
||||
assert(full_size % sizeof(void*) == 0);
|
||||
assert(full_size < max_encoded_offset || (page->busy_size == full_size && page_offset == 0));
|
||||
header->full_size = static_cast<uint16_t>(full_size < max_encoded_offset ? full_size / sizeof(void*) : 0);
|
||||
|
||||
// round-trip through void* to avoid 'cast increases required alignment of target type' warning
|
||||
// header is guaranteed a pointer-sized alignment, which should be enough for char_t
|
||||
|
@ -597,11 +601,11 @@ PUGI__NS_BEGIN
|
|||
assert(header);
|
||||
|
||||
// deallocate
|
||||
size_t page_offset = sizeof(xml_memory_page) + header->page_offset;
|
||||
size_t page_offset = sizeof(xml_memory_page) + header->page_offset * sizeof(void*);
|
||||
xml_memory_page* page = reinterpret_cast<xml_memory_page*>(static_cast<void*>(reinterpret_cast<char*>(header) - page_offset));
|
||||
|
||||
// if full_size == 0 then this string occupies the whole page
|
||||
size_t full_size = header->full_size == 0 ? page->busy_size : header->full_size;
|
||||
size_t full_size = header->full_size == 0 ? page->busy_size : header->full_size * sizeof(void*);
|
||||
|
||||
deallocate_memory(header, full_size, page);
|
||||
}
|
||||
|
@ -2894,23 +2898,28 @@ PUGI__NS_BEGIN
|
|||
|
||||
char_t* parse_doctype_ignore(char_t* s)
|
||||
{
|
||||
size_t depth = 0;
|
||||
|
||||
assert(s[0] == '<' && s[1] == '!' && s[2] == '[');
|
||||
s++;
|
||||
s += 3;
|
||||
|
||||
while (*s)
|
||||
{
|
||||
if (s[0] == '<' && s[1] == '!' && s[2] == '[')
|
||||
{
|
||||
// nested ignore section
|
||||
s = parse_doctype_ignore(s);
|
||||
if (!s) return s;
|
||||
s += 3;
|
||||
depth++;
|
||||
}
|
||||
else if (s[0] == ']' && s[1] == ']' && s[2] == '>')
|
||||
{
|
||||
// ignore section end
|
||||
s += 3;
|
||||
|
||||
return s;
|
||||
if (depth == 0)
|
||||
return s;
|
||||
|
||||
depth--;
|
||||
}
|
||||
else s++;
|
||||
}
|
||||
|
@ -2918,10 +2927,12 @@ PUGI__NS_BEGIN
|
|||
PUGI__THROW_ERROR(status_bad_doctype, s);
|
||||
}
|
||||
|
||||
char_t* parse_doctype_group(char_t* s, char_t endch, bool toplevel)
|
||||
char_t* parse_doctype_group(char_t* s, char_t endch)
|
||||
{
|
||||
size_t depth = 0;
|
||||
|
||||
assert((s[0] == '<' || s[0] == 0) && s[1] == '!');
|
||||
s++;
|
||||
s += 2;
|
||||
|
||||
while (*s)
|
||||
{
|
||||
|
@ -2936,12 +2947,8 @@ PUGI__NS_BEGIN
|
|||
else
|
||||
{
|
||||
// some control group
|
||||
s = parse_doctype_group(s, endch, false);
|
||||
if (!s) return s;
|
||||
|
||||
// skip >
|
||||
assert(*s == '>');
|
||||
s++;
|
||||
s += 2;
|
||||
depth++;
|
||||
}
|
||||
}
|
||||
else if (s[0] == '<' || s[0] == '"' || s[0] == '\'')
|
||||
|
@ -2952,12 +2959,16 @@ PUGI__NS_BEGIN
|
|||
}
|
||||
else if (*s == '>')
|
||||
{
|
||||
return s;
|
||||
if (depth == 0)
|
||||
return s;
|
||||
|
||||
depth--;
|
||||
s++;
|
||||
}
|
||||
else s++;
|
||||
}
|
||||
|
||||
if (!toplevel || endch != '>') PUGI__THROW_ERROR(status_bad_doctype, s);
|
||||
if (depth != 0 || endch != '>') PUGI__THROW_ERROR(status_bad_doctype, s);
|
||||
|
||||
return s;
|
||||
}
|
||||
|
@ -3049,7 +3060,7 @@ PUGI__NS_BEGIN
|
|||
|
||||
char_t* mark = s + 9;
|
||||
|
||||
s = parse_doctype_group(s, endch, true);
|
||||
s = parse_doctype_group(s, endch);
|
||||
if (!s) return s;
|
||||
|
||||
assert((*s == 0 && endch == '>') || *s == '>');
|
||||
|
@ -3989,6 +4000,27 @@ PUGI__NS_BEGIN
|
|||
writer.write('-', '-', '>');
|
||||
}
|
||||
|
||||
PUGI__FN void node_output_pi_value(xml_buffered_writer& writer, const char_t* s)
|
||||
{
|
||||
while (*s)
|
||||
{
|
||||
const char_t* prev = s;
|
||||
|
||||
// look for ?> sequence - we can't output it since ?> terminates PI
|
||||
while (*s && !(s[0] == '?' && s[1] == '>')) ++s;
|
||||
|
||||
writer.write_buffer(prev, static_cast<size_t>(s - prev));
|
||||
|
||||
if (*s)
|
||||
{
|
||||
assert(s[0] == '?' && s[1] == '>');
|
||||
|
||||
writer.write('?', ' ', '>');
|
||||
s += 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PUGI__FN void node_output_attributes(xml_buffered_writer& writer, xml_node_struct* node, unsigned int flags)
|
||||
{
|
||||
const char_t* default_name = PUGIXML_TEXT(":anonymous");
|
||||
|
@ -4102,7 +4134,7 @@ PUGI__NS_BEGIN
|
|||
if (static_cast<xml_node_pi_struct*>(node)->pi_value)
|
||||
{
|
||||
writer.write(' ');
|
||||
writer.write_string(static_cast<xml_node_pi_struct*>(node)->pi_value);
|
||||
node_output_pi_value(writer, static_cast<xml_node_pi_struct*>(node)->pi_value);
|
||||
}
|
||||
|
||||
writer.write('?', '>');
|
||||
|
@ -4863,7 +4895,7 @@ PUGI__NS_BEGIN
|
|||
PUGI__FN xml_parse_result load_buffer_impl(xml_document_struct* doc, xml_node_struct* root, void* contents, size_t size, unsigned int options, xml_encoding encoding, bool is_mutable, bool own, char_t** out_buffer)
|
||||
{
|
||||
// check input buffer
|
||||
assert(contents || size == 0);
|
||||
if (!contents && size) return make_parse_result(status_io_error);
|
||||
|
||||
// get actual encoding
|
||||
xml_encoding buffer_encoding = impl::get_buffer_encoding(encoding, contents, size);
|
||||
|
@ -8066,7 +8098,7 @@ PUGI__NS_BEGIN
|
|||
return node.attribute() ? namespace_uri(node.attribute(), node.parent()) : namespace_uri(node.node());
|
||||
}
|
||||
|
||||
PUGI__FN void normalize_space(char_t* buffer)
|
||||
PUGI__FN char_t* normalize_space(char_t* buffer)
|
||||
{
|
||||
char_t* write = buffer;
|
||||
|
||||
|
@ -8090,9 +8122,11 @@ PUGI__NS_BEGIN
|
|||
|
||||
// zero-terminate
|
||||
*write = 0;
|
||||
|
||||
return write;
|
||||
}
|
||||
|
||||
PUGI__FN void translate(char_t* buffer, const char_t* from, const char_t* to, size_t to_length)
|
||||
PUGI__FN char_t* translate(char_t* buffer, const char_t* from, const char_t* to, size_t to_length)
|
||||
{
|
||||
char_t* write = buffer;
|
||||
|
||||
|
@ -8110,6 +8144,8 @@ PUGI__NS_BEGIN
|
|||
|
||||
// zero-terminate
|
||||
*write = 0;
|
||||
|
||||
return write;
|
||||
}
|
||||
|
||||
PUGI__FN unsigned char* translate_table_generate(xpath_allocator* alloc, const char_t* from, const char_t* to)
|
||||
|
@ -8146,7 +8182,7 @@ PUGI__NS_BEGIN
|
|||
return static_cast<unsigned char*>(result);
|
||||
}
|
||||
|
||||
PUGI__FN void translate_table(char_t* buffer, const unsigned char* table)
|
||||
PUGI__FN char_t* translate_table(char_t* buffer, const unsigned char* table)
|
||||
{
|
||||
char_t* write = buffer;
|
||||
|
||||
|
@ -8172,6 +8208,8 @@ PUGI__NS_BEGIN
|
|||
|
||||
// zero-terminate
|
||||
*write = 0;
|
||||
|
||||
return write;
|
||||
}
|
||||
|
||||
inline bool is_xpath_attribute(const char_t* name)
|
||||
|
@ -10278,18 +10316,20 @@ PUGI__NS_BEGIN
|
|||
{
|
||||
xpath_string s = string_value(c.n, stack.result);
|
||||
|
||||
normalize_space(s.data(stack.result));
|
||||
char_t* begin = s.data(stack.result);
|
||||
char_t* end = normalize_space(begin);
|
||||
|
||||
return s;
|
||||
return xpath_string::from_heap_preallocated(begin, end);
|
||||
}
|
||||
|
||||
case ast_func_normalize_space_1:
|
||||
{
|
||||
xpath_string s = _left->eval_string(c, stack);
|
||||
|
||||
normalize_space(s.data(stack.result));
|
||||
char_t* begin = s.data(stack.result);
|
||||
char_t* end = normalize_space(begin);
|
||||
|
||||
return s;
|
||||
return xpath_string::from_heap_preallocated(begin, end);
|
||||
}
|
||||
|
||||
case ast_func_translate:
|
||||
|
@ -10302,18 +10342,20 @@ PUGI__NS_BEGIN
|
|||
xpath_string from = _right->eval_string(c, swapped_stack);
|
||||
xpath_string to = _right->_next->eval_string(c, swapped_stack);
|
||||
|
||||
translate(s.data(stack.result), from.c_str(), to.c_str(), to.length());
|
||||
char_t* begin = s.data(stack.result);
|
||||
char_t* end = translate(begin, from.c_str(), to.c_str(), to.length());
|
||||
|
||||
return s;
|
||||
return xpath_string::from_heap_preallocated(begin, end);
|
||||
}
|
||||
|
||||
case ast_opt_translate_table:
|
||||
{
|
||||
xpath_string s = _left->eval_string(c, stack);
|
||||
|
||||
translate_table(s.data(stack.result), _data.table);
|
||||
char_t* begin = s.data(stack.result);
|
||||
char_t* end = translate_table(begin, _data.table);
|
||||
|
||||
return s;
|
||||
return xpath_string::from_heap_preallocated(begin, end);
|
||||
}
|
||||
|
||||
case ast_variable:
|
||||
|
|
|
@ -66,6 +66,50 @@ namespace
|
|||
VirtualProtect(rptr, aligned_size + PAGE_SIZE, PAGE_NOACCESS, &old_flags);
|
||||
}
|
||||
}
|
||||
#elif defined(__APPLE__) || defined(__linux__)
|
||||
# include <sys/mman.h>
|
||||
|
||||
namespace
|
||||
{
|
||||
const size_t PAGE_SIZE = 4096;
|
||||
|
||||
size_t align_to_page(size_t value)
|
||||
{
|
||||
return (value + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1);
|
||||
}
|
||||
|
||||
void* allocate_page_aligned(size_t size)
|
||||
{
|
||||
return mmap(0, size + PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
|
||||
}
|
||||
|
||||
void* allocate(size_t size)
|
||||
{
|
||||
size_t aligned_size = align_to_page(size);
|
||||
|
||||
void* ptr = allocate_page_aligned(aligned_size + PAGE_SIZE);
|
||||
if (!ptr) return 0;
|
||||
|
||||
char* end = static_cast<char*>(ptr) + aligned_size;
|
||||
|
||||
int res = mprotect(end, PAGE_SIZE, PROT_NONE);
|
||||
assert(res == 0);
|
||||
(void)!res;
|
||||
|
||||
return end - size;
|
||||
}
|
||||
|
||||
void deallocate(void* ptr, size_t size)
|
||||
{
|
||||
size_t aligned_size = align_to_page(size);
|
||||
|
||||
void* rptr = static_cast<char*>(ptr) + size - aligned_size;
|
||||
|
||||
int res = mprotect(rptr, aligned_size + PAGE_SIZE, PROT_NONE);
|
||||
assert(res == 0);
|
||||
(void)!res;
|
||||
}
|
||||
}
|
||||
#else
|
||||
# include <stdlib.h>
|
||||
|
||||
|
|
|
@ -65,8 +65,8 @@ if ($fast)
|
|||
|
||||
print "### autotest begin " . scalar localtime() . "\n";
|
||||
|
||||
# print SVN revision info
|
||||
print "### autotest revision $1\n" if (`svn info` =~ /Revision:\s+(\d+)/);
|
||||
# print Git revision info
|
||||
print "### autotest revision $1\n" if (`git rev-parse HEAD` =~ /(.+)/);
|
||||
|
||||
# get CPU info
|
||||
$cpucount = &getcpucount();
|
||||
|
|
|
@ -32,6 +32,6 @@ exit unless $client;
|
|||
|
||||
select $client;
|
||||
|
||||
&execprint('svn up') == 0 || die "error updating from repo\n";
|
||||
&execprint('git pull') == 0 || die "error updating from repo\n";
|
||||
&execprint('perl tests/autotest-local.pl') == 0 || die "error launching tests\n";
|
||||
system($exitcmd);
|
||||
|
|
|
@ -128,7 +128,7 @@ while (<>)
|
|||
$defines{$_} = 1 foreach (split /,/, $defineset);
|
||||
&insertindex(\%configurations, $fullconf);
|
||||
}
|
||||
elsif (/^### autotest revision (\d+)/)
|
||||
elsif (/^### autotest revision (.+)/)
|
||||
{
|
||||
if (defined $revision && $revision != $1)
|
||||
{
|
||||
|
@ -224,6 +224,6 @@ $date = localtime;
|
|||
|
||||
print <<END;
|
||||
</table><br>
|
||||
Generated on $date from Subversion r$revision
|
||||
Generated on $date from Git $revision
|
||||
</body></html>
|
||||
END
|
||||
|
|
|
@ -71,6 +71,15 @@ bool test_double_nan(double value)
|
|||
}
|
||||
|
||||
#ifndef PUGIXML_NO_XPATH
|
||||
static size_t strlength(const pugi::char_t* s)
|
||||
{
|
||||
#ifdef PUGIXML_WCHAR_MODE
|
||||
return wcslen(s);
|
||||
#else
|
||||
return strlen(s);
|
||||
#endif
|
||||
}
|
||||
|
||||
bool test_xpath_string(const pugi::xpath_node& node, const pugi::char_t* query, pugi::xpath_variable_set* variables, const pugi::char_t* expected)
|
||||
{
|
||||
pugi::xpath_query q(query, variables);
|
||||
|
@ -81,7 +90,11 @@ bool test_xpath_string(const pugi::xpath_node& node, const pugi::char_t* query,
|
|||
|
||||
size_t size = q.evaluate_string(result, capacity, node);
|
||||
|
||||
if (size <= capacity) return test_string_equal(result, expected);
|
||||
if (size != strlength(expected) + 1)
|
||||
return false;
|
||||
|
||||
if (size <= capacity)
|
||||
return test_string_equal(result, expected);
|
||||
|
||||
std::basic_string<pugi::char_t> buffer(size, ' ');
|
||||
|
||||
|
|
|
@ -990,6 +990,17 @@ TEST(document_load_buffer_empty_fragment)
|
|||
}
|
||||
}
|
||||
|
||||
TEST(document_load_buffer_null)
|
||||
{
|
||||
xml_document doc;
|
||||
|
||||
CHECK(doc.load_buffer(0, 12).status == status_io_error && !doc.first_child());
|
||||
CHECK(doc.load_buffer(0, 12, parse_fragment).status == status_io_error && !doc.first_child());
|
||||
|
||||
CHECK(doc.load_buffer_inplace(0, 12).status == status_io_error && !doc.first_child());
|
||||
CHECK(doc.load_buffer_inplace_own(0, 12).status == status_io_error && !doc.first_child());
|
||||
}
|
||||
|
||||
TEST(document_progressive_truncation)
|
||||
{
|
||||
char* original_data;
|
||||
|
|
|
@ -2,7 +2,8 @@
|
|||
|
||||
#include <limits>
|
||||
#include <string>
|
||||
#include <cmath>
|
||||
|
||||
#include <math.h>
|
||||
|
||||
TEST_XML(dom_attr_assign, "<node/>")
|
||||
{
|
||||
|
@ -1488,7 +1489,7 @@ TEST(dom_fp_roundtrip_float)
|
|||
{
|
||||
for (size_t i = 0; i < sizeof(fp_roundtrip_base) / sizeof(fp_roundtrip_base[0]); ++i)
|
||||
{
|
||||
float value = ldexpf(fp_roundtrip_base[i], e);
|
||||
float value = ldexpf(static_cast<float>(fp_roundtrip_base[i]), e);
|
||||
|
||||
doc.text().set(value);
|
||||
CHECK(doc.text().as_float() == value);
|
||||
|
|
|
@ -863,6 +863,7 @@ TEST(parse_declaration_error)
|
|||
TEST(parse_empty)
|
||||
{
|
||||
xml_document doc;
|
||||
|
||||
CHECK(doc.load_string(STR("")).status == status_no_document_element && !doc.first_child());
|
||||
CHECK(doc.load_string(STR(""), parse_fragment) && !doc.first_child());
|
||||
}
|
||||
|
|
|
@ -322,3 +322,43 @@ TEST(parse_doctype_error_ignore)
|
|||
CHECK(doc.load_string(STR("<!DOCTYPE root [ <![IGNORE[ <![INCLUDE[")).status == status_bad_doctype);
|
||||
CHECK(doc.load_string(STR("<!DOCTYPE root [ <![IGNORE[ <![INCLUDE["), parse_doctype).status == status_bad_doctype);
|
||||
}
|
||||
|
||||
TEST(parse_doctype_stackless_group)
|
||||
{
|
||||
std::basic_string<char_t> str;
|
||||
|
||||
int count = 100000;
|
||||
|
||||
str += STR("<!DOCTYPE ");
|
||||
|
||||
for (int i = 0; i < count; ++i)
|
||||
str += STR("<!G ");
|
||||
|
||||
for (int j = 0; j < count; ++j)
|
||||
str += STR(">");
|
||||
|
||||
str += STR(">");
|
||||
|
||||
xml_document doc;
|
||||
CHECK(doc.load_string(str.c_str(), parse_fragment));
|
||||
}
|
||||
|
||||
TEST(parse_doctype_stackless_ignore)
|
||||
{
|
||||
std::basic_string<char_t> str;
|
||||
|
||||
int count = 100000;
|
||||
|
||||
str += STR("<!DOCTYPE ");
|
||||
|
||||
for (int i = 0; i < count; ++i)
|
||||
str += STR("<![IGNORE[ ");
|
||||
|
||||
for (int j = 0; j < count; ++j)
|
||||
str += STR("]]>");
|
||||
|
||||
str += STR(">");
|
||||
|
||||
xml_document doc;
|
||||
CHECK(doc.load_string(str.c_str(), parse_fragment));
|
||||
}
|
||||
|
|
|
@ -115,6 +115,25 @@ TEST(write_pi_null)
|
|||
CHECK_NODE(doc, STR("<?:anonymous value?>"));
|
||||
}
|
||||
|
||||
TEST(write_pi_invalid)
|
||||
{
|
||||
xml_document doc;
|
||||
xml_node node = doc.append_child(node_pi);
|
||||
|
||||
node.set_name(STR("test"));
|
||||
node.set_value(STR("?"));
|
||||
|
||||
CHECK_NODE(doc, STR("<?test ?" "?>"));
|
||||
|
||||
node.set_value(STR("?>"));
|
||||
|
||||
CHECK_NODE(doc, STR("<?test ? >?>"));
|
||||
|
||||
node.set_value(STR("<?foo?>"));
|
||||
|
||||
CHECK_NODE(doc, STR("<?test <?foo? >?>"));
|
||||
}
|
||||
|
||||
TEST_XML_FLAGS(write_declaration, "<?xml version='2.0'?>", parse_declaration | parse_fragment)
|
||||
{
|
||||
CHECK_NODE(doc, STR("<?xml version=\"2.0\"?>"));
|
||||
|
@ -171,7 +190,7 @@ struct test_writer: xml_writer
|
|||
virtual void write(const void* data, size_t size)
|
||||
{
|
||||
CHECK(size % sizeof(pugi::char_t) == 0);
|
||||
contents += std::basic_string<pugi::char_t>(static_cast<const pugi::char_t*>(data), static_cast<const pugi::char_t*>(data) + size / sizeof(pugi::char_t));
|
||||
contents.append(static_cast<const pugi::char_t*>(data), size / sizeof(pugi::char_t));
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -570,6 +570,14 @@ TEST(xpath_string_translate_table)
|
|||
CHECK_XPATH_STRING(c, STR("translate('abcde', 'abcd', concat('ABC', 'D'))"), STR("ABCDe"));
|
||||
}
|
||||
|
||||
TEST(xpath_string_translate_remove)
|
||||
{
|
||||
xml_node c;
|
||||
|
||||
CHECK_XPATH_STRING(c, STR("translate('000000755', '0', '')"), STR("755"));
|
||||
CHECK_XPATH_STRING(c, STR("translate('000000755', concat('0', ''), '')"), STR("755"));
|
||||
}
|
||||
|
||||
TEST_XML(xpath_nodeset_last, "<node><c1/><c1/><c2/><c3/><c3/><c3/><c3/></node>")
|
||||
{
|
||||
xml_node n = doc.child(STR("node"));
|
||||
|
|
|
@ -15,7 +15,7 @@ static bool test_narrow(const std::string& result, const char* expected, size_t
|
|||
|
||||
void xml_writer_string::write(const void* data, size_t size)
|
||||
{
|
||||
contents += std::string(static_cast<const char*>(data), size);
|
||||
contents.append(static_cast<const char*>(data), size);
|
||||
}
|
||||
|
||||
std::string xml_writer_string::as_narrow() const
|
||||
|
|
Loading…
Add table
Reference in a new issue