compareNodePosition method

int compareNodePosition(
  1. XmlNode other
)

Compares the position of this node and other.

Returns 0 if the nodes are the same, -1 if this node is before the argument, and 1 if after. Throws a StateError, if the nodes do not share a parent.

Implementation note: The code takes great care to avoid unnecessary object allocation (intermediate lists) since this code might be called a lot.

Implementation

int compareNodePosition(XmlNode other) {
  if (this == other) return 0;
  XmlNode? node1 = this, node2 = other;
  var depth1 = node1.depth, depth2 = node2.depth;
  if (depth1 > depth2) {
    while (node1 != null && depth1 > depth2) {
      node1 = node1.parent;
      depth1--;
    }
    if (node1 == node2) return 1;
  } else if (depth2 > depth1) {
    while (node2 != null && depth2 > depth1) {
      node2 = node2.parent;
      depth2--;
    }
    if (node1 == node2) return -1;
  }
  while (node1 != null && node2 != null && node1.parent != node2.parent) {
    node1 = node1.parent;
    node2 = node2.parent;
  }
  if (node1 != null && node2 != null) {
    final parent = node1.parent;
    assert(parent == node2.parent);
    if (parent != null) {
      for (final attribute in parent.attributes) {
        if (attribute == node1) return -1;
        if (attribute == node2) return 1;
      }
      for (final child in parent.children) {
        if (child == node1) return -1;
        if (child == node2) return 1;
      }
    }
  }
  throw StateError('$this and $other are in disconnected DOM trees.');
}