123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262 |
- // Copyright (c) 2001 Per M.A. Bothner and Brainfood Inc.
- // This is free software; for terms and warranty disclaimer see ./COPYING.
- package gnu.lists;
- /**
- * A position that can also go down and up in a tree.
- * A TreePosition is a stack of positions. The "current" position
- * (i.e. the one you get if you tree the TreePosition as a SeqPosition)
- * is that in the innermost containing sequence.
- *
- * Normally, the "current" element is (the one following) a position in a
- * sequence. As a special (initial case), we may want to treat the
- * entire sequence is the "current element". This is represented by depth==-1
- * and xpos set to the root element (which need not actually be a sequence).
- */
- public class TreePosition extends SeqPosition implements Cloneable
- {
- /** Used when depth==-1 to indicate the "entire" object.
- * Usually an AbstractSequence, but need not be. */
- private Object xpos;
- /** Stack of pushed values for sequence. */
- AbstractSequence[] sstack;
- /** Stack of pushed values for iposition. */
- int[] istack;
- /** Depth of the above stacks.
- * Note that getDepth returns depth+1; this should perhaps match. */
- int depth;
- /** Start of stacks - anything below 'start' is ignored.
- * This is useful for pushing/pop positions without object allocation. */
- int start;
- public TreePosition()
- {
- depth = -1;
- }
- /** Not a position *in* a sequence, but the current element is the entire sequence. */
- public TreePosition(Object root)
- {
- xpos = root;
- depth = -1;
- }
- public TreePosition(AbstractSequence seq, int index)
- {
- super(seq, index, false);
- }
- public TreePosition (TreePosition pos)
- {
- set(pos);
- }
- public Object clone ()
- {
- return new TreePosition(this);
- }
- public void set (TreePosition position)
- {
- release();
- int d = position.depth;
- depth = d;
- if (d < 0)
- {
- xpos = position.xpos;
- return;
- }
- if (sstack == null || sstack.length <= d)
- sstack = new AbstractSequence[d + 10];
- if (istack == null || istack.length <= d)
- istack = new int[d + 10];
- AbstractSequence seq;
- int i;
- for (i = 0; i < depth; i++)
- {
- int j = i + position.start;
- seq = position.sstack[j];
- sstack[depth-1] = seq;
- istack[depth - i] = seq.copyPos(position.istack[j]);
- }
- seq = position.sequence;
- sequence = seq;
- ipos = seq.copyPos(position.ipos);
- }
- /** Number of ancestor sequences, including current sequence. */
- public int getDepth()
- {
- return depth + 1;
- }
- /** Get the "root document". */
- public AbstractSequence getRoot()
- {
- return depth == 0 ? sequence : sstack[start];
- }
- public Object getPosNext()
- {
- return sequence == null ? xpos : sequence.getPosNext(ipos);
- }
- public void push(AbstractSequence child, int iposChild)
- {
- int d = depth + start;
- if (d >= 0)
- {
- if (d == 0)
- {
- istack = new int[8];
- sstack = new AbstractSequence[8];
- }
- else if (d >= istack.length)
- {
- int ndepth = 2 * d;
- int[] itemp = new int[ndepth];
- Object[] xtemp = new Object[ndepth];
- AbstractSequence[] stemp = new AbstractSequence[ndepth];
- System.arraycopy(istack, 0, itemp, 0, depth);
- System.arraycopy(sstack, 0, stemp, 0, depth);
- istack = itemp;
- sstack = stemp;
- }
- sstack[d] = sequence;
- istack[d] = ipos;
- }
- depth++;
- sequence = child;
- ipos = iposChild;
- }
- public void pop()
- {
- sequence.releasePos(ipos);
- popNoRelease();
- }
- public void popNoRelease()
- {
- if (--depth < 0)
- {
- xpos = sequence;
- sequence = null;
- }
- else
- {
- sequence = sstack[start+depth];
- ipos = istack[start+depth];
- }
- }
- public final boolean gotoParent()
- {
- return sequence == null ? false : sequence.gotoParent(this);
- }
- /** Set position before first child (of the element following position).
- * @return true if there is a child sequence (which might be empty);
- * false if current position is end of sequence or following element
- * is atomic (cannot have children).
- */
- public boolean gotoChildrenStart()
- {
- if (sequence == null)
- {
- if (! (xpos instanceof AbstractSequence))
- return false;
- depth = 0;
- sequence = (AbstractSequence) xpos;
- setPos(sequence.startPos());
- }
- else
- {
- if (! sequence.gotoChildrenStart(this))
- return false;
- }
- return true;
- }
- /** Set position before first attribute (of the element following position).
- * This is used to iterate through the sequence of attributes.
- */
- public boolean gotoAttributesStart()
- {
- if (sequence == null)
- {
- if (xpos instanceof AbstractSequence)
- {
- // ??? FIXME
- }
- return false;
- }
- return sequence.gotoAttributesStart(this);
- }
- /*
- public boolean gotoAttribute(Object name)
- {
- return sequence.gotoAttribute(this);
- }
- */
- /** Get the value of an ancestor node.
- * @param up the number parents to go up.
- * @return if up is 0, same getNext. Otherwise get parent
- * applied as specified.
- */
- public Object getAncestor(int up)
- {
- if (up == 0)
- return sequence.getPosNext(ipos);
- int i = depth - up;
- if (i <= 0)
- return getRoot();
- i += start;
- return sstack[i].getPosNext(istack[i]);
- }
- public void release()
- {
- while (sequence != null)
- {
- sequence.releasePos(ipos);
- pop();
- }
- xpos = null;
- }
- /** Copy this position into pos. */
- /*
- public void clone (Position pos)
- {
- // FIXME!
- }
- public Object clone()
- {
- TreePosition pos = new TreePosition();
- clone(pos);
- return pos;
- }
- */
- public void dump()
- {
- System.err.println("TreePosition dump depth:"+depth+" start:"+start);
- for (int i = 0; i <= depth; i++)
- {
- AbstractSequence seq = i==0 ? sequence : sstack[depth-i];
- System.err.print("#"+i+" seq:"+seq);
- System.err.println(" ipos:" + (i == 0 ? ipos : istack[depth-i]));
- }
- }
- }
|