diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/pugixml.cpp | 105 |
1 files changed, 62 insertions, 43 deletions
diff --git a/src/pugixml.cpp b/src/pugixml.cpp index 163af21..5e9c4b8 100644 --- a/src/pugixml.cpp +++ b/src/pugixml.cpp @@ -1845,7 +1845,11 @@ PUGI__NS_BEGIN char_t* buffer = static_cast<char_t*>(xml_memory::allocate((length + 1) * sizeof(char_t))); 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; out_buffer = buffer; @@ -3016,8 +3020,6 @@ PUGI__NS_BEGIN PUGI__PUSHNODE(node_doctype); cursor->contents = mark; - - PUGI__POPNODE(); } } else if (*s == 0 && endch == '-') PUGI__THROW_ERROR(status_bad_comment, s); @@ -4156,7 +4158,7 @@ PUGI__NS_BEGIN while (node != root); } - PUGI__FN bool has_declaration(const xml_node node) + PUGI__FN bool has_declaration(xml_node node) { for (xml_node child = node.first_child(); child; child = child.next_sibling()) { @@ -4187,7 +4189,7 @@ PUGI__NS_BEGIN return true; } - PUGI__FN bool allow_move(const xml_node parent, const xml_node child) + PUGI__FN bool allow_move(xml_node parent, xml_node child) { // check that child can be a child of parent if (!allow_insert_child(parent.type(), child.type())) @@ -7875,7 +7877,7 @@ PUGI__NS_BEGIN prefix_length = pos ? static_cast<size_t>(pos - name) : 0; } - bool operator()(const xml_attribute a) const + bool operator()(xml_attribute a) const { const char_t* name = a.name(); @@ -7885,7 +7887,7 @@ PUGI__NS_BEGIN } }; - PUGI__FN const char_t* namespace_uri(const xml_node node) + PUGI__FN const char_t* namespace_uri(xml_node node) { namespace_uri_predicate pred = node.name(); @@ -7903,7 +7905,7 @@ PUGI__NS_BEGIN return PUGIXML_TEXT(""); } - PUGI__FN const char_t* namespace_uri(const xml_attribute attr, const xml_node parent) + PUGI__FN const char_t* namespace_uri(xml_attribute attr, xml_node parent) { namespace_uri_predicate pred = attr.name(); @@ -8318,6 +8320,8 @@ PUGI__NS_BEGIN 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 capacity = static_cast<size_t>(_eos - _begin); size_t count = static_cast<size_t>(end_ - begin_); @@ -9051,44 +9055,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(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->rettype() == xpath_type_number) + + if (expr->eval_boolean(c, stack)) { - if (expr->eval_number(c, stack) == i) - { - *last++ = *it; + *last++ = *it; - if (once) break; - } + if (once) break; } - else + } + + ns.truncate(last); + } + + 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) { - if (expr->eval_boolean(c, stack)) - { - *last++ = *it; + *last++ = *it; - if (once) break; - } + if (once) break; } } - + 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_const(xpath_node_set_raw& ns, size_t first, xpath_ast_node* expr, const xpath_stack& stack) { assert(ns.size() >= first); assert(expr->rettype() == xpath_type_number); @@ -9116,21 +9135,28 @@ PUGI__NS_BEGIN 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) { if (ns.size() == first) return; - + bool last_once = eval_once(ns.type() == xpath_node_set::type_sorted, eval); for (xpath_ast_node* pred = _right; pred; pred = pred->_next) - { - 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); - } + pred->apply_predicate(ns, first, stack, !pred->_next && last_once); } bool step_push(xpath_node_set_raw& ns, xml_attribute_struct* a, xml_node_struct* parent, xpath_allocator* alloc) @@ -10208,16 +10234,9 @@ PUGI__NS_BEGIN // either expression is a number or it contains position() call; sort by document order if (_test != predicate_posinv) set.sort_do(); - if (_test == predicate_constant || _test == predicate_constant_one) - { - apply_predicate_const(set, 0, _right, stack); - } - else - { - bool once = eval_once(set.type() == xpath_node_set::type_sorted, eval); + 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; } |