Pugixml XML parser

Update to upstream master
This commit is contained in:
Laurent Trinques
2020-07-26 16:14:31 +02:00
parent a2eb92803a
commit 9cdc023f31
3 changed files with 115 additions and 89 deletions

View File

@@ -72,4 +72,3 @@
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/

View File

@@ -378,7 +378,7 @@ PUGI__NS_BEGIN
static PUGI__UNSIGNED_OVERFLOW unsigned int hash(const void* key)
{
unsigned int h = static_cast<unsigned int>(reinterpret_cast<uintptr_t>(key));
unsigned int h = static_cast<unsigned int>(reinterpret_cast<uintptr_t>(key) & 0xffffffff);
// MurmurHash3 32-bit finalizer
h ^= h >> 16;
@@ -4435,6 +4435,9 @@ PUGI__NS_BEGIN
while (sit && sit != sn)
{
// loop invariant: dit is inside the subtree rooted at dn
assert(dit);
// when a tree is copied into one of the descendants, we need to skip that subtree to avoid an infinite loop
if (sit != dn)
{
@@ -4464,9 +4467,14 @@ PUGI__NS_BEGIN
sit = sit->parent;
dit = dit->parent;
// loop invariant: dit is inside the subtree rooted at dn while sit is inside sn
assert(sit == sn || dit);
}
while (sit != sn);
}
assert(!sit || dit == dn->parent);
}
PUGI__FN void node_copy_attribute(xml_attribute_struct* da, xml_attribute_struct* sa)
@@ -6949,8 +6957,7 @@ namespace pugi
{
reset();
for (xml_node cur = proto.first_child(); cur; cur = cur.next_sibling())
append_copy(cur);
impl::node_copy_tree(_root, proto._root);
}
PUGI__FN void xml_document::_create()
@@ -10414,35 +10421,38 @@ PUGI__NS_BEGIN
if (_rettype == xpath_type_boolean)
return _data.variable->get_boolean();
// variable needs to be converted to the correct type, this is handled by the fallthrough block below
break;
}
// fallthrough
default:
{
switch (_rettype)
{
case xpath_type_number:
return convert_number_to_boolean(eval_number(c, stack));
case xpath_type_string:
{
xpath_allocator_capture cr(stack.result);
return !eval_string(c, stack).empty();
}
case xpath_type_node_set:
{
xpath_allocator_capture cr(stack.result);
return !eval_node_set(c, stack, nodeset_eval_any).empty();
}
default:
assert(false && "Wrong expression for return type boolean"); // unreachable
return false;
}
;
}
// none of the ast types that return the value directly matched, we need to perform type conversion
switch (_rettype)
{
case xpath_type_number:
return convert_number_to_boolean(eval_number(c, stack));
case xpath_type_string:
{
xpath_allocator_capture cr(stack.result);
return !eval_string(c, stack).empty();
}
case xpath_type_node_set:
{
xpath_allocator_capture cr(stack.result);
return !eval_node_set(c, stack, nodeset_eval_any).empty();
}
default:
assert(false && "Wrong expression for return type boolean"); // unreachable
return false;
}
}
@@ -10549,36 +10559,38 @@ PUGI__NS_BEGIN
if (_rettype == xpath_type_number)
return _data.variable->get_number();
// variable needs to be converted to the correct type, this is handled by the fallthrough block below
break;
}
// fallthrough
default:
{
switch (_rettype)
{
case xpath_type_boolean:
return eval_boolean(c, stack) ? 1 : 0;
case xpath_type_string:
{
xpath_allocator_capture cr(stack.result);
return convert_string_to_number(eval_string(c, stack).c_str());
}
case xpath_type_node_set:
{
xpath_allocator_capture cr(stack.result);
return convert_string_to_number(eval_string(c, stack).c_str());
}
default:
assert(false && "Wrong expression for return type number"); // unreachable
return 0;
}
;
}
// none of the ast types that return the value directly matched, we need to perform type conversion
switch (_rettype)
{
case xpath_type_boolean:
return eval_boolean(c, stack) ? 1 : 0;
case xpath_type_string:
{
xpath_allocator_capture cr(stack.result);
return convert_string_to_number(eval_string(c, stack).c_str());
}
case xpath_type_node_set:
{
xpath_allocator_capture cr(stack.result);
return convert_string_to_number(eval_string(c, stack).c_str());
}
default:
assert(false && "Wrong expression for return type number"); // unreachable
return 0;
}
}
@@ -10833,34 +10845,37 @@ PUGI__NS_BEGIN
if (_rettype == xpath_type_string)
return xpath_string::from_const(_data.variable->get_string());
// variable needs to be converted to the correct type, this is handled by the fallthrough block below
break;
}
// fallthrough
default:
{
switch (_rettype)
{
case xpath_type_boolean:
return xpath_string::from_const(eval_boolean(c, stack) ? PUGIXML_TEXT("true") : PUGIXML_TEXT("false"));
case xpath_type_number:
return convert_number_to_string(eval_number(c, stack), stack.result);
case xpath_type_node_set:
{
xpath_allocator_capture cr(stack.temp);
xpath_stack swapped_stack = {stack.temp, stack.result};
xpath_node_set_raw ns = eval_node_set(c, swapped_stack, nodeset_eval_first);
return ns.empty() ? xpath_string() : string_value(ns.first(), stack.result);
}
default:
assert(false && "Wrong expression for return type string"); // unreachable
return xpath_string();
}
;
}
// none of the ast types that return the value directly matched, we need to perform type conversion
switch (_rettype)
{
case xpath_type_boolean:
return xpath_string::from_const(eval_boolean(c, stack) ? PUGIXML_TEXT("true") : PUGIXML_TEXT("false"));
case xpath_type_number:
return convert_number_to_string(eval_number(c, stack), stack.result);
case xpath_type_node_set:
{
xpath_allocator_capture cr(stack.temp);
xpath_stack swapped_stack = {stack.temp, stack.result};
xpath_node_set_raw ns = eval_node_set(c, swapped_stack, nodeset_eval_first);
return ns.empty() ? xpath_string() : string_value(ns.first(), stack.result);
}
default:
assert(false && "Wrong expression for return type string"); // unreachable
return xpath_string();
}
}
@@ -10982,13 +10997,18 @@ PUGI__NS_BEGIN
return ns;
}
// variable needs to be converted to the correct type, this is handled by the fallthrough block below
break;
}
// fallthrough
default:
assert(false && "Wrong expression for return type node set"); // unreachable
return xpath_node_set_raw();
;
}
// none of the ast types that return the value directly matched, but conversions to node set are invalid
assert(false && "Wrong expression for return type node set"); // unreachable
return xpath_node_set_raw();
}
void optimize(xpath_allocator* alloc)
@@ -11063,7 +11083,7 @@ PUGI__NS_BEGIN
// Use optimized path for @attr = 'value' or @attr = $value
if (_type == ast_op_equal &&
_left && _right && // workaround for clang static analyzer and Coverity (_left and _right are never null for ast_op_equal)
// coverity[mixed_enums]
// coverity[mixed_enums]
_left->_type == ast_step && _left->_axis == axis_attribute && _left->_test == nodetest_name && !_left->_left && !_left->_right &&
(_right->_type == ast_string_constant || (_right->_type == ast_variable && _right->_rettype == xpath_type_string)))
{
@@ -12926,4 +12946,3 @@ namespace pugi
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/

View File

@@ -111,6 +111,15 @@
# endif
#endif
// If C++ is 2011 or higher, use 'nullptr'
#ifndef PUGIXML_NULL
# if __cplusplus >= 201103
# define PUGIXML_NULL nullptr
# else
# define PUGIXML_NULL 0
# endif
#endif
// Character interface macros
#ifdef PUGIXML_WCHAR_MODE
# define PUGIXML_TEXT(t) L ## t
@@ -661,15 +670,15 @@ namespace pugi
#ifndef PUGIXML_NO_XPATH
// Select single node by evaluating XPath query. Returns first node from the resulting node set.
xpath_node select_node(const char_t* query, xpath_variable_set* variables = 0) const;
xpath_node select_node(const char_t* query, xpath_variable_set* variables = PUGIXML_NULL) const;
xpath_node select_node(const xpath_query& query) const;
// Select node set by evaluating XPath query
xpath_node_set select_nodes(const char_t* query, xpath_variable_set* variables = 0) const;
xpath_node_set select_nodes(const char_t* query, xpath_variable_set* variables = PUGIXML_NULL) const;
xpath_node_set select_nodes(const xpath_query& query) const;
// (deprecated: use select_node instead) Select single node by evaluating XPath query.
PUGIXML_DEPRECATED xpath_node select_single_node(const char_t* query, xpath_variable_set* variables = 0) const;
PUGIXML_DEPRECATED xpath_node select_single_node(const char_t* query, xpath_variable_set* variables = PUGIXML_NULL) const;
PUGIXML_DEPRECATED xpath_node select_single_node(const xpath_query& query) const;
#endif
@@ -1212,7 +1221,7 @@ namespace pugi
public:
// Construct a compiled object from XPath expression.
// If PUGIXML_NO_EXCEPTIONS is not defined, throws xpath_exception on compilation errors.
explicit xpath_query(const char_t* query, xpath_variable_set* variables = 0);
explicit xpath_query(const char_t* query, xpath_variable_set* variables = PUGIXML_NULL);
// Constructor
xpath_query();
@@ -1488,4 +1497,3 @@ namespace std
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/