mirror of
https://github.com/zeux/pugixml.git
synced 2024-12-28 14:48:43 +08:00
:Merge remote-tracking branch 'upstream/master'
This commit is contained in:
commit
1912894f53
4
Makefile
4
Makefile
@ -30,7 +30,7 @@ all: $(EXECUTABLE)
|
|||||||
|
|
||||||
ifeq ($(config),coverage)
|
ifeq ($(config),coverage)
|
||||||
test: $(EXECUTABLE)
|
test: $(EXECUTABLE)
|
||||||
@find $(BUILD) -name '*.gcda' | xargs rm
|
@find $(BUILD) -name '*.gcda' | xargs -r rm
|
||||||
./$(EXECUTABLE)
|
./$(EXECUTABLE)
|
||||||
@gcov -b -c $(BUILD)/src/pugixml.cpp.gcda | sed -e '/./{H;$!d;}' -e 'x;/pugixml.cpp/!d;'
|
@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
|
@ls *.gcov | grep -v pugixml.cpp.gcov | xargs rm
|
||||||
@ -51,4 +51,4 @@ $(BUILD)/%.o: %
|
|||||||
|
|
||||||
-include $(OBJECTS:.o=.d)
|
-include $(OBJECTS:.o=.d)
|
||||||
|
|
||||||
.PHONY: all test clean
|
.PHONY: all test clean
|
||||||
|
@ -1352,7 +1352,11 @@ PUGI__NS_BEGIN
|
|||||||
char_t* buffer = static_cast<char_t*>(xml_memory::allocate((length + 1) * sizeof(char_t)));
|
char_t* buffer = static_cast<char_t*>(xml_memory::allocate((length + 1) * sizeof(char_t)));
|
||||||
if (!buffer) return false;
|
if (!buffer) return false;
|
||||||
|
|
||||||
memcpy(buffer, contents, length * sizeof(char_t));
|
if (contents)
|
||||||
|
memcpy(buffer, contents, length * sizeof(char_t));
|
||||||
|
else
|
||||||
|
assert(length == 0);
|
||||||
|
|
||||||
buffer[length] = 0;
|
buffer[length] = 0;
|
||||||
|
|
||||||
out_buffer = buffer;
|
out_buffer = buffer;
|
||||||
@ -7769,6 +7773,8 @@ PUGI__NS_BEGIN
|
|||||||
|
|
||||||
void append(const xpath_node* begin_, const xpath_node* end_, xpath_allocator* alloc)
|
void append(const xpath_node* begin_, const xpath_node* end_, xpath_allocator* alloc)
|
||||||
{
|
{
|
||||||
|
if (begin_ == end_) return;
|
||||||
|
|
||||||
size_t size_ = static_cast<size_t>(_end - _begin);
|
size_t size_ = static_cast<size_t>(_end - _begin);
|
||||||
size_t capacity = static_cast<size_t>(_eos - _begin);
|
size_t capacity = static_cast<size_t>(_eos - _begin);
|
||||||
size_t count = static_cast<size_t>(end_ - begin_);
|
size_t count = static_cast<size_t>(end_ - begin_);
|
||||||
@ -8502,44 +8508,59 @@ PUGI__NS_BEGIN
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void apply_predicate(xpath_node_set_raw& ns, size_t first, xpath_ast_node* expr, const xpath_stack& stack, bool once)
|
static void apply_predicate_boolean(xpath_node_set_raw& ns, size_t first, xpath_ast_node* expr, const xpath_stack& stack, bool once)
|
||||||
{
|
{
|
||||||
assert(ns.size() >= first);
|
assert(ns.size() >= first);
|
||||||
|
assert(expr->rettype() != xpath_type_number);
|
||||||
|
|
||||||
size_t i = 1;
|
size_t i = 1;
|
||||||
size_t size = ns.size() - first;
|
size_t size = ns.size() - first;
|
||||||
|
|
||||||
xpath_node* last = ns.begin() + first;
|
xpath_node* last = ns.begin() + first;
|
||||||
|
|
||||||
// remove_if... or well, sort of
|
// remove_if... or well, sort of
|
||||||
for (xpath_node* it = last; it != ns.end(); ++it, ++i)
|
for (xpath_node* it = last; it != ns.end(); ++it, ++i)
|
||||||
{
|
{
|
||||||
xpath_context c(*it, i, size);
|
xpath_context c(*it, i, size);
|
||||||
|
|
||||||
if (expr->rettype() == xpath_type_number)
|
|
||||||
{
|
|
||||||
if (expr->eval_number(c, stack) == i)
|
|
||||||
{
|
|
||||||
*last++ = *it;
|
|
||||||
|
|
||||||
if (once) break;
|
if (expr->eval_boolean(c, stack))
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
if (expr->eval_boolean(c, stack))
|
*last++ = *it;
|
||||||
{
|
|
||||||
*last++ = *it;
|
|
||||||
|
|
||||||
if (once) break;
|
if (once) break;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ns.truncate(last);
|
ns.truncate(last);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void apply_predicate_const(xpath_node_set_raw& ns, size_t first, xpath_ast_node* expr, const xpath_stack& stack)
|
static void apply_predicate_number(xpath_node_set_raw& ns, size_t first, xpath_ast_node* expr, const xpath_stack& stack, bool once)
|
||||||
|
{
|
||||||
|
assert(ns.size() >= first);
|
||||||
|
assert(expr->rettype() == xpath_type_number);
|
||||||
|
|
||||||
|
size_t i = 1;
|
||||||
|
size_t size = ns.size() - first;
|
||||||
|
|
||||||
|
xpath_node* last = ns.begin() + first;
|
||||||
|
|
||||||
|
// remove_if... or well, sort of
|
||||||
|
for (xpath_node* it = last; it != ns.end(); ++it, ++i)
|
||||||
|
{
|
||||||
|
xpath_context c(*it, i, size);
|
||||||
|
|
||||||
|
if (expr->eval_number(c, stack) == i)
|
||||||
|
{
|
||||||
|
*last++ = *it;
|
||||||
|
|
||||||
|
if (once) break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ns.truncate(last);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void apply_predicate_number_const(xpath_node_set_raw& ns, size_t first, xpath_ast_node* expr, const xpath_stack& stack)
|
||||||
{
|
{
|
||||||
assert(ns.size() >= first);
|
assert(ns.size() >= first);
|
||||||
assert(expr->rettype() == xpath_type_number);
|
assert(expr->rettype() == xpath_type_number);
|
||||||
@ -8567,21 +8588,28 @@ PUGI__NS_BEGIN
|
|||||||
ns.truncate(last);
|
ns.truncate(last);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void apply_predicate(xpath_node_set_raw& ns, size_t first, const xpath_stack& stack, bool once)
|
||||||
|
{
|
||||||
|
if (ns.size() == first) return;
|
||||||
|
|
||||||
|
assert(_type == ast_filter || _type == ast_predicate);
|
||||||
|
|
||||||
|
if (_test == predicate_constant || _test == predicate_constant_one)
|
||||||
|
apply_predicate_number_const(ns, first, _right, stack);
|
||||||
|
else if (_right->rettype() == xpath_type_number)
|
||||||
|
apply_predicate_number(ns, first, _right, stack, once);
|
||||||
|
else
|
||||||
|
apply_predicate_boolean(ns, first, _right, stack, once);
|
||||||
|
}
|
||||||
|
|
||||||
void apply_predicates(xpath_node_set_raw& ns, size_t first, const xpath_stack& stack, nodeset_eval_t eval)
|
void apply_predicates(xpath_node_set_raw& ns, size_t first, const xpath_stack& stack, nodeset_eval_t eval)
|
||||||
{
|
{
|
||||||
if (ns.size() == first) return;
|
if (ns.size() == first) return;
|
||||||
|
|
||||||
bool last_once = eval_once(ns.type() == xpath_node_set::type_sorted, eval);
|
bool last_once = eval_once(ns.type() == xpath_node_set::type_sorted, eval);
|
||||||
|
|
||||||
for (xpath_ast_node* pred = _right; pred; pred = pred->_next)
|
for (xpath_ast_node* pred = _right; pred; pred = pred->_next)
|
||||||
{
|
pred->apply_predicate(ns, first, stack, !pred->_next && last_once);
|
||||||
assert(pred->_type == ast_predicate);
|
|
||||||
|
|
||||||
if (pred->_test == predicate_constant || pred->_test == predicate_constant_one)
|
|
||||||
apply_predicate_const(ns, first, pred->_right, stack);
|
|
||||||
else
|
|
||||||
apply_predicate(ns, first, pred->_right, stack, !pred->_next && last_once);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool step_push(xpath_node_set_raw& ns, xml_attribute_struct* a, xml_node_struct* parent, xpath_allocator* alloc)
|
bool step_push(xpath_node_set_raw& ns, xml_attribute_struct* a, xml_node_struct* parent, xpath_allocator* alloc)
|
||||||
@ -9659,16 +9687,9 @@ PUGI__NS_BEGIN
|
|||||||
// either expression is a number or it contains position() call; sort by document order
|
// either expression is a number or it contains position() call; sort by document order
|
||||||
if (_test != predicate_posinv) set.sort_do();
|
if (_test != predicate_posinv) set.sort_do();
|
||||||
|
|
||||||
if (_test == predicate_constant || _test == predicate_constant_one)
|
bool once = eval_once(set.type() == xpath_node_set::type_sorted, eval);
|
||||||
{
|
|
||||||
apply_predicate_const(set, 0, _right, stack);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
bool once = eval_once(set.type() == xpath_node_set::type_sorted, eval);
|
|
||||||
|
|
||||||
apply_predicate(set, 0, _right, stack, once);
|
apply_predicate(set, 0, stack, once);
|
||||||
}
|
|
||||||
|
|
||||||
return set;
|
return set;
|
||||||
}
|
}
|
||||||
|
@ -301,6 +301,10 @@ TEST(document_load_file_error)
|
|||||||
|
|
||||||
CHECK(doc.load_file("filedoesnotexist").status == status_file_not_found);
|
CHECK(doc.load_file("filedoesnotexist").status == status_file_not_found);
|
||||||
|
|
||||||
|
#ifndef _WIN32
|
||||||
|
CHECK(doc.load_file("/dev/tty").status == status_io_error);
|
||||||
|
#endif
|
||||||
|
|
||||||
test_runner::_memory_fail_threshold = 1;
|
test_runner::_memory_fail_threshold = 1;
|
||||||
CHECK(doc.load_file("tests/data/small.xml").status == status_out_of_memory);
|
CHECK(doc.load_file("tests/data/small.xml").status == status_out_of_memory);
|
||||||
}
|
}
|
||||||
|
@ -1091,6 +1091,19 @@ TEST_XML(dom_node_append_buffer_fragment, "<node />")
|
|||||||
CHECK_NODE(doc, STR("<node>1234</node>"));
|
CHECK_NODE(doc, STR("<node>1234</node>"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_XML(dom_node_append_buffer_empty, "<node />")
|
||||||
|
{
|
||||||
|
xml_node node = doc.child(STR("node"));
|
||||||
|
|
||||||
|
CHECK(node.append_buffer("", 0).status == status_no_document_element);
|
||||||
|
CHECK(node.append_buffer("", 0, parse_fragment).status == status_ok);
|
||||||
|
|
||||||
|
CHECK(node.append_buffer(0, 0).status == status_no_document_element);
|
||||||
|
CHECK(node.append_buffer(0, 0, parse_fragment).status == status_ok);
|
||||||
|
|
||||||
|
CHECK_NODE(doc, STR("<node />"));
|
||||||
|
}
|
||||||
|
|
||||||
TEST_XML(dom_node_prepend_move, "<node>foo<child/></node>")
|
TEST_XML(dom_node_prepend_move, "<node>foo<child/></node>")
|
||||||
{
|
{
|
||||||
xml_node child = doc.child(STR("node")).child(STR("child"));
|
xml_node child = doc.child(STR("node")).child(STR("child"));
|
||||||
|
@ -481,4 +481,52 @@ TEST(xpath_operators_associativity_arithmetic)
|
|||||||
CHECK_XPATH_NUMBER(c, STR("1-1+1"), 1);
|
CHECK_XPATH_NUMBER(c, STR("1-1+1"), 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(xpath_operators_mod)
|
||||||
|
{
|
||||||
|
// Check that mod operator conforms to Java spec (since this is the only concrete source of information about XPath mod)
|
||||||
|
xml_node c;
|
||||||
|
|
||||||
|
// Basic tests from spec
|
||||||
|
CHECK_XPATH_NUMBER(c, STR("5 mod 3"), 2);
|
||||||
|
CHECK_XPATH_NUMBER(c, STR("5 mod -3"), 2);
|
||||||
|
CHECK_XPATH_NUMBER(c, STR("-5 mod 3"), -2);
|
||||||
|
CHECK_XPATH_NUMBER(c, STR("-5 mod -3"), -2);
|
||||||
|
|
||||||
|
// If either operand is NaN, the result is NaN
|
||||||
|
CHECK_XPATH_NUMBER_NAN(c, STR("(0 div 0) mod 3"));
|
||||||
|
CHECK_XPATH_NUMBER_NAN(c, STR("3 mod (0 div 0)"));
|
||||||
|
CHECK_XPATH_NUMBER_NAN(c, STR("(0 div 0) mod (0 div 0)"));
|
||||||
|
|
||||||
|
// If the dividend is an infinity, or the divisor is a zero, or both, the result is NaN
|
||||||
|
CHECK_XPATH_NUMBER_NAN(c, STR("(1 div 0) mod 3"));
|
||||||
|
CHECK_XPATH_NUMBER_NAN(c, STR("(1 div 0) mod -3"));
|
||||||
|
CHECK_XPATH_NUMBER_NAN(c, STR("(-1 div 0) mod 3"));
|
||||||
|
CHECK_XPATH_NUMBER_NAN(c, STR("1 mod 0"));
|
||||||
|
CHECK_XPATH_NUMBER_NAN(c, STR("-1 mod 0"));
|
||||||
|
CHECK_XPATH_NUMBER_NAN(c, STR("(1 div 0) mod 0"));
|
||||||
|
CHECK_XPATH_NUMBER_NAN(c, STR("(-1 div 0) mod 0"));
|
||||||
|
|
||||||
|
// If the dividend is finite and the divisor is an infinity, the result equals the dividend
|
||||||
|
CHECK_XPATH_NUMBER(c, STR("1 mod (1 div 0)"), 1);
|
||||||
|
CHECK_XPATH_NUMBER(c, STR("1 mod (-1 div 0)"), 1);
|
||||||
|
CHECK_XPATH_NUMBER(c, STR("-1 mod (1 div 0)"), -1);
|
||||||
|
CHECK_XPATH_NUMBER(c, STR("0 mod (1 div 0)"), 0);
|
||||||
|
CHECK_XPATH_NUMBER(c, STR("0 mod (-1 div 0)"), 0);
|
||||||
|
CHECK_XPATH_NUMBER(c, STR("100000 mod (1 div 0)"), 100000);
|
||||||
|
|
||||||
|
// If the dividend is a zero and the divisor is finite, the result equals the dividend.
|
||||||
|
CHECK_XPATH_NUMBER(c, STR("0 mod 1000000"), 0);
|
||||||
|
CHECK_XPATH_NUMBER(c, STR("0 mod -1000000"), 0);
|
||||||
|
|
||||||
|
// In the remaining cases ... the floating-point remainder r from the division of a dividend n by a divisor d
|
||||||
|
// is defined by the mathematical relation r = n - (d * q) where q is an integer that is negative only if n/d is
|
||||||
|
// negative and positive only if n/d is positive, and whose magnitude is as large as possible without exceeding the magnitude of the true
|
||||||
|
// mathematical quotient of n and d.
|
||||||
|
CHECK_XPATH_NUMBER(c, STR("9007199254740991 mod 2"), 1);
|
||||||
|
CHECK_XPATH_NUMBER(c, STR("9007199254740991 mod 3"), 1);
|
||||||
|
CHECK_XPATH_NUMBER(c, STR("18446744073709551615 mod 2"), 0);
|
||||||
|
CHECK_XPATH_NUMBER(c, STR("18446744073709551615 mod 3"), 1);
|
||||||
|
CHECK_XPATH_NUMBER(c, STR("115792089237316195423570985008687907853269984665640564039457584007913129639935 mod 2"), 0);
|
||||||
|
CHECK_XPATH_NUMBER(c, STR("115792089237316195423570985008687907853269984665640564039457584007913129639935 mod 3"), 1);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -664,6 +664,8 @@ TEST_XML(xpath_paths_optimize_step_once, "<node><para1><para2/><para3/><para4><p
|
|||||||
|
|
||||||
CHECK_XPATH_BOOLEAN(doc, STR("//para5/ancestor-or-self::*"), true);
|
CHECK_XPATH_BOOLEAN(doc, STR("//para5/ancestor-or-self::*"), true);
|
||||||
CHECK_XPATH_BOOLEAN(doc, STR("//para5/ancestor::*"), true);
|
CHECK_XPATH_BOOLEAN(doc, STR("//para5/ancestor::*"), true);
|
||||||
|
|
||||||
|
CHECK_XPATH_BOOLEAN(doc, STR("//@attr5/ancestor-or-self::node()"), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_XML(xpath_paths_null_nodeset_entries, "<node attr='value'/>")
|
TEST_XML(xpath_paths_null_nodeset_entries, "<node attr='value'/>")
|
||||||
|
Loading…
x
Reference in New Issue
Block a user