1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889 |
- // Copyright (c) 2003, 2008 Per M.A. Bothner.
- // This is free software; for terms and warranty disclaimer see ./COPYING.
- package gnu.kawa.xml;
- import gnu.lists.*;
- import gnu.xml.*;
- /** Manages a sequence of node references in document order without duplicates.
- * The most recently added element is just before the gap.
- * Optimized for the data being in order, or at least having good
- * locality (a node being "near" the previously-entered node).
- */
- public class SortedNodes extends Nodes {
- private int compareIndex(int index, AbstractSequence seq2, int ipos2) {
- AbstractSequence seq1 = vector.getSeq(index);
- int ipos1 = vector.getPos(index);
- return AbstractSequence.compare(seq1, ipos1, seq2, ipos2);
- }
- /** Find index where to put position (seq, ipos).
- * Require {@code index>=start && index<end},
- * where {@code end==start+count}.
- * Require all position before index are "less than" (seq, ipos),
- * and all positions after are "greater than" (seq, ipos).
- * If there is no such index (because it is "same as"), return -1.
- */
- private int find (int start, int count, AbstractSequence seq, int ipos) {
- int lo = 0;
- int hi = count;
- // We use binary search, though the arraycopy operations in
- // writePosition limit the benefit - a sequence of writePosition
- // calls is still quadratic in the worst case
- // (but linear if locality is good).
- while (lo < hi) {
- int mid = (lo + hi) >>> 1;
- int cmp = compareIndex(start + mid, seq, ipos);
- if (cmp == 0)
- return -1;
- if (cmp > 0)
- hi = mid;
- else
- lo = mid + 1;
- }
- return start + lo;
- }
- int find(AbstractSequence seq, int ipos) {
- int count = size();
- if (count <= 0)
- return 0;
- // Optimize for the already sorted case, or secondarily for good
- // locality. So use the gapStart as the initial "mid-point".
- int lastIndex = vector.getLastIndex();
- int cmp = lastIndex < 0 ? -1 : compareIndex(lastIndex, seq, ipos);
- if (cmp < 0) {
- // The new node is after all nodes up to gapStart.
- int i = lastIndex+1;
- // Note that if the incoming nodes are already sorted (a
- // common case in path expressions), then find will
- // immediately return i.
- return find (i, count-i, seq, ipos);
- } else if (cmp == 0)
- return -1;
- else {
- return find (0, lastIndex, seq, ipos);
- }
- }
- @Override
- public void writePosition(SeqPosition position) {
- AbstractSequence seq = position.sequence;
- int ipos = position.ipos;
- int i = find(seq, ipos);
- if (i >= 0)
- vector.add(i, position);
- }
- @Override
- public void writePosition(AbstractSequence seq, int ipos) {
- int i = find(seq, ipos);
- if (i >= 0) {
- vector.add(i, (SeqPosition) null);
- vector.setBuffer(i, seq, ipos);
- }
- }
- }
|