#include "config.h"
#include "BoundaryPoint.h"
#include "ContainerNode.h"
namespace WebCore {
template PartialOrdering treeOrder<Tree>(const BoundaryPoint&, const BoundaryPoint&);
template PartialOrdering treeOrder< ShadowIncludingTree >(const BoundaryPoint&, const BoundaryPoint&);
template PartialOrdering treeOrder<ComposedTree>(const BoundaryPoint&, const BoundaryPoint&);
Optional<BoundaryPoint> makeBoundaryPointBeforeNode(Node& node)
{
auto parent = node.parentNode();
if (!parent)
return WTF::nullopt;
return BoundaryPoint { *parent, node.computeNodeIndex() };
}
Optional<BoundaryPoint> makeBoundaryPointAfterNode(Node& node)
{
auto parent = node.parentNode();
if (!parent)
return WTF::nullopt;
return BoundaryPoint { *parent, node.computeNodeIndex() + 1 };
}
static bool isOffsetBeforeChild(ContainerNode& container, unsigned offset, Node& child)
{
if (!offset)
return true;
if (child.parentNode() != &container)
return false;
unsigned currentOffset = 0;
for (auto currentChild = container.firstChild(); currentChild && currentChild != &child; currentChild = currentChild->nextSibling()) {
if (offset <= ++currentOffset)
return true;
}
return false;
}
static PartialOrdering order(unsigned a, unsigned b)
{
if (a < b)
return PartialOrdering::less;
if (a > b)
return PartialOrdering::greater;
return PartialOrdering::equivalent;
}
template<TreeType treeType> PartialOrdering treeOrder(const BoundaryPoint& a, const BoundaryPoint& b)
{
if (a.container.ptr() == b.container.ptr())
return order(a.offset, b.offset);
for (auto ancestor = b.container.ptr(); ancestor; ) {
auto nextAncestor = parent<treeType>(*ancestor);
if (nextAncestor == a.container.ptr())
return isOffsetBeforeChild(*nextAncestor, a.offset, *ancestor) ? PartialOrdering::less : PartialOrdering::greater;
ancestor = nextAncestor;
}
for (auto ancestor = a.container.ptr(); ancestor; ) {
auto nextAncestor = parent<treeType>(*ancestor);
if (nextAncestor == b.container.ptr())
return isOffsetBeforeChild(*nextAncestor, b.offset, *ancestor) ? PartialOrdering::greater : PartialOrdering::less;
ancestor = nextAncestor;
}
return treeOrder<treeType>(a.container, b.container);
}
PartialOrdering treeOrderForTesting(TreeType type, const BoundaryPoint& a, const BoundaryPoint& b)
{
switch (type) {
case Tree:
return treeOrder<Tree>(a, b);
case ShadowIncludingTree:
return treeOrder<ShadowIncludingTree>(a, b);
case ComposedTree:
return treeOrder<ComposedTree>(a, b);
}
ASSERT_NOT_REACHED();
return PartialOrdering::unordered;
}
}