XPath: Document order comparator refactoring, document order is now a total order even for nodes from different documents
git-svn-id: http://pugixml.googlecode.com/svn/trunk@695 99668b35-9821-0410-8761-19e4c4f06640
This commit is contained in:
parent
70115fa9ab
commit
b1939bd6f8
@ -4819,25 +4819,26 @@ namespace
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// precondition: node_height of ln is <= node_height of rn, ln != rn
|
|
||||||
bool node_is_before(xml_node ln, unsigned int lh, xml_node rn, unsigned int rh)
|
bool node_is_before(xml_node ln, unsigned int lh, xml_node rn, unsigned int rh)
|
||||||
{
|
{
|
||||||
assert(lh <= rh);
|
// normalize heights
|
||||||
|
for (unsigned int h = rh; h < lh; h++) ln = ln.parent();
|
||||||
|
for (unsigned int h = lh; h < rh; h++) rn = rn.parent();
|
||||||
|
|
||||||
while (lh < rh)
|
// one node is the ancestor of the other
|
||||||
{
|
if (ln == rn) return lh < rh;
|
||||||
--rh;
|
|
||||||
rn = rn.parent();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ln == rn) return true;
|
|
||||||
|
|
||||||
|
// find common ancestor
|
||||||
while (ln.parent() != rn.parent())
|
while (ln.parent() != rn.parent())
|
||||||
{
|
{
|
||||||
ln = ln.parent();
|
ln = ln.parent();
|
||||||
rn = rn.parent();
|
rn = rn.parent();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// there is no common ancestor (the shared parent is null), nodes are from different documents
|
||||||
|
if (!ln.parent()) return ln < rn;
|
||||||
|
|
||||||
|
// determine sibling order
|
||||||
for (; ln; ln = ln.next_sibling())
|
for (; ln; ln = ln.next_sibling())
|
||||||
if (ln == rn)
|
if (ln == rn)
|
||||||
return true;
|
return true;
|
||||||
@ -4858,15 +4859,19 @@ namespace
|
|||||||
{
|
{
|
||||||
xml_node ln = lhs.node(), rn = rhs.node();
|
xml_node ln = lhs.node(), rn = rhs.node();
|
||||||
|
|
||||||
|
// optimized document order based check
|
||||||
const void* lo = lhs.attribute() ? lhs.attribute().document_order() : ln.document_order();
|
const void* lo = lhs.attribute() ? lhs.attribute().document_order() : ln.document_order();
|
||||||
const void* ro = rhs.attribute() ? rhs.attribute().document_order() : rn.document_order();
|
const void* ro = rhs.attribute() ? rhs.attribute().document_order() : rn.document_order();
|
||||||
|
|
||||||
if (lo && ro) return lo < ro;
|
if (lo && ro) return lo < ro;
|
||||||
|
|
||||||
|
// compare attributes
|
||||||
if (lhs.attribute() && rhs.attribute())
|
if (lhs.attribute() && rhs.attribute())
|
||||||
{
|
{
|
||||||
|
// shared parent
|
||||||
if (lhs.parent() == rhs.parent())
|
if (lhs.parent() == rhs.parent())
|
||||||
{
|
{
|
||||||
|
// determine sibling order
|
||||||
for (xml_attribute a = lhs.attribute(); a; a = a.next_attribute())
|
for (xml_attribute a = lhs.attribute(); a; a = a.next_attribute())
|
||||||
if (a == rhs.attribute())
|
if (a == rhs.attribute())
|
||||||
return true;
|
return true;
|
||||||
@ -4874,17 +4879,20 @@ namespace
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// compare attribute parents
|
||||||
ln = lhs.parent();
|
ln = lhs.parent();
|
||||||
rn = rhs.parent();
|
rn = rhs.parent();
|
||||||
}
|
}
|
||||||
else if (lhs.attribute())
|
else if (lhs.attribute())
|
||||||
{
|
{
|
||||||
|
// attributes go after the parent element
|
||||||
if (lhs.parent() == rhs.node()) return false;
|
if (lhs.parent() == rhs.node()) return false;
|
||||||
|
|
||||||
ln = lhs.parent();
|
ln = lhs.parent();
|
||||||
}
|
}
|
||||||
else if (rhs.attribute())
|
else if (rhs.attribute())
|
||||||
{
|
{
|
||||||
|
// attributes go after the parent element
|
||||||
if (rhs.parent() == lhs.node()) return true;
|
if (rhs.parent() == lhs.node()) return true;
|
||||||
|
|
||||||
rn = rhs.parent();
|
rn = rhs.parent();
|
||||||
@ -4895,7 +4903,7 @@ namespace
|
|||||||
unsigned int lh = node_height(ln);
|
unsigned int lh = node_height(ln);
|
||||||
unsigned int rh = node_height(rn);
|
unsigned int rh = node_height(rn);
|
||||||
|
|
||||||
return (lh <= rh) ? node_is_before(ln, lh, rn, rh) : !node_is_before(rn, rh, ln, lh);
|
return node_is_before(ln, lh, rn, rh);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user