123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953 |
- // Copyright (c) 2001, 2002, 2003, 2005 Per M.A. Bothner and Brainfood Inc.
- // This is free software; for terms and warranty disclaimer see ./COPYING.
- package gnu.lists;
- import gnu.kawa.util.HashUtils;
- import java.util.*;
- /**
- * A collection of default methods for implementing sequence-like classes.
- *
- * Additionally, a sequence may have zero or more attributes, which are
- * name-value pairs. A sequence may also have a named "type". These
- * extensions are to support XML functionality - it might be cleaner to
- * move them to a sub-class of Sequence or some interface.
- *
- * Many of the protected methods in Sequence (such as nextIndex) are
- * only intended to be called from SeqPosition or TreePosition, see those.
- *
- * @author Per Bothner
- */
- public abstract class AbstractSequence<E>
- {
- public static final int[] noInts = new int[0];
- public int size() {
- if (rank() == 1) return getSize(0);
- throw unsupported("size");
- }
- public int getSize() {
- int sz = 1;
- for (int r = rank(); --r >= 0; )
- sz *= getSize(r);
- return sz;
- }
- public boolean isEmpty()
- {
- return size() == 0;
- }
- public int rank()
- {
- return 1;
- }
- protected void checkRank(int i) {
- if (i != rank())
- throw badRank(i);
- }
- protected RuntimeException badRank(int i) {
- return new RuntimeException("wrong number of indexes "+i+" to "+rank()+"-rank array");
- }
- // FIXME remove this - some implementations needed
- public Array<E> asImmutable() { throw unsupported("asImmutable"); }
- public E get() { return getRaw(effectiveIndex()); }
- public E get(int i) {
- return getRaw(effectiveIndex(i));
- }
- public E get(int i, int j) { return getRaw(effectiveIndex(i,j)); }
- public E get(int i, int j, int k, int... rest) {
- return getRaw(effectiveIndex(i, j, k, rest)); }
- public E get(int[] indexes) {
- return getRaw(effectiveIndex(indexes));
- }
- protected void checkCanWrite () {
- }
- public E getRowMajor(int index) {
- if (rank() == 1)
- return get(index);
- if (this instanceof Array)
- return Arrays.getRowMajor((Array<E>) this, index);
- throw unsupportedException("getRowMajor");
- }
- public int effectiveIndex() {
- checkRank(0);
- return 0;
- }
- public int effectiveIndex(int index) {
- checkRank(1);
- return index - getLowBound(0);
- }
- public int effectiveIndex(int i, int j) {
- checkRank(2);
- return (i - getLowBound(0)) * getSize(1) + (j - getLowBound(1));
- }
- public int effectiveIndex(int i, int j, int k, int... rest) {
- int r = rest.length;
- checkRank(3+r);
- int eff = 0;
- int stride = 1;
- while (--r >= 0) {
- eff += (rest[r] - getLowBound(3+r)) * stride;
- stride *= getSize(3+r);
- }
- eff += (k - getLowBound(2)) * stride;
- stride *= getSize(2);
- eff += (j - getLowBound(1)) * stride;
- stride *= getSize(1);
- eff += (i - getLowBound(0)) * stride;
- return eff;
- }
- public int effectiveIndex(int[] indexes) {
- int ilength = indexes.length;
- switch (indexes.length) {
- case 0:
- return effectiveIndex();
- case 1:
- return effectiveIndex(indexes[0]);
- case 2:
- return effectiveIndex(indexes[0], indexes[1]);
- default:
- int[] rest;
- if (ilength == 3)
- rest = noInts;
- else {
- rest = new int[ilength-3];
- System.arraycopy(indexes, 3, rest, 0, ilength-3);
- }
- return effectiveIndex(indexes[0], indexes[1], indexes[2], rest);
- }
- }
- public E getRaw(int index) { throw unsupported("getRaw"); }
- protected void setBuffer(Object obj) { throw unsupported("setBuffer"); }
- /** Given an "effective index", set selected element. */
- public void setRaw(int index, E value) { throw unsupported("setRaw"); }
- public boolean getBooleanRaw(int index) {
- Object value = getRaw(index);
- return value != null && ((Boolean) value).booleanValue();
- }
- public char getCharRaw(int index) {
- return ((Character) getRaw(index)).charValue();
- }
- public byte getByteRaw(int index) {
- return ((Number) getRaw(index)).byteValue();
- }
- public short getShortRaw(int index) {
- return ((Number) getRaw(index)).shortValue();
- }
- public int getIntRaw(int index) {
- return ((Number) getRaw(index)).intValue();
- }
- public long getLongRaw(int index) {
- return ((Number) getRaw(index)).longValue();
- }
- public float getFloatRaw(int index) {
- return ((Number) getRaw(index)).floatValue();
- }
- public double getDoubleRaw(int index) {
- return ((Number) getRaw(index)).doubleValue();
- }
- public int getInt() { return getIntRaw(effectiveIndex()); }
- public int getInt(int i) { return getIntRaw(effectiveIndex(i)); }
- public int getInt(int i, int j) { return getIntRaw(effectiveIndex(i,j)); }
- public int getInt(int i, int j, int k, int... rest) {
- return getIntRaw(effectiveIndex(i, j, k, rest)); }
- public int getInt(int[] indexes) {
- return getIntRaw(effectiveIndex(indexes));
- }
- public void set(int[] indexes, E value) {
- checkCanWrite();
- setRaw(effectiveIndex(indexes), value);
- }
- public int getLowBound(int dim)
- {
- return 0;
- }
- public int getSize (int dim)
- {
- return dim==0 ? size() : 1;
- }
- public int getElementKind() { return Sequence.OBJECT_VALUE; }
- protected RuntimeException unsupported (String text)
- {
- return unsupportedException(getClass().getName()
- + " does not implement " + text);
- }
- public static RuntimeException unsupportedException (String text)
- {
- return new UnsupportedOperationException(text);
- }
- public E set(int index, E value) {
- checkCanWrite();
- int effi = effectiveIndex(index);
- E old = (E) getRaw(effi);
- setRaw(effi, value);
- return old;
- }
- public void setAt(int index, E value) {
- checkCanWrite();
- setRaw(effectiveIndex(index), value);
- }
- public void fill(E value)
- {
- for (int i = startPos(); (i = nextPos(i)) != 0; )
- setPosPrevious(i, value);
- }
- public void fillPosRange(int fromPos, int toPos, E value)
- {
- int i = copyPos(fromPos);
- for (; compare(i, toPos) < 0; i = nextPos(i))
- setPosNext(i, value);
- releasePos(i);
- }
- public void fill(int fromIndex, int toIndex, E value)
- {
- int i = createPos(fromIndex, false);
- int limit = createPos(toIndex, true);
- for (; compare(i, limit) < 0; i = nextPos(i))
- setPosNext(i, value);
- releasePos(i);
- releasePos(limit);
- }
- // FIXME?
- //public final Object elementAt (int index) { return get(index); }
- /** See java.util.List. */
- public int indexOf(Object o)
- {
- int i = 0;
- for (int iter = startPos(); (iter = nextPos(iter)) != 0; i++)
- {
- Object v = getPosPrevious(iter);
- if (o==null ? v==null : o.equals(v))
- {
- releasePos(iter);
- return i;
- }
- }
- return -1;
- }
- /** See java.util.List. */
- public int lastIndexOf(Object o)
- {
- // FIXME use iterator?
- for (int n = size(); --n >= 0; )
- {
- Object e = get(n);
- if (o==null ? e == null : o.equals(e))
- return n;
- }
- return -1;
- }
- /** Get next matching child or descendent (ignoring attributes).
- * @param startPos starting position
- * @param type a test (predicate) to apply to selected elements
- * @param endPos stop before endPos
- * @param descend if true do depth-first traversal.
- * @return poistion of next match or 0 if none found
- */
- public int nextMatching(int startPos, ItemPredicate type,
- int endPos, boolean descend)
- {
- if (descend)
- throw unsupported("nextMatching with descend");
- int ipos = startPos;
- for (;;)
- {
- if (compare(ipos, endPos) >= 0)
- return 0;
- ipos = nextPos(ipos);
- if (type.isInstancePos(this, ipos))
- return ipos;
- }
- }
- /** See java.util.List. */
- public boolean contains(Object o)
- {
- return indexOf(o) >= 0;
- }
- /** See java.util.List. */
- public boolean containsAll(Collection<?> c)
- {
- Iterator<?> i = c.iterator();
- while (i.hasNext())
- {
- Object e = i.next();
- if (! contains(e))
- return false;
- }
- return true;
- }
- public final Enumeration<E> elements()
- {
- return getIterator(0);
- }
- public final SeqPosition<E, AbstractSequence<E>> getIterator()
- {
- return getIterator(0);
- }
- public SeqPosition<E, AbstractSequence<E>> getIterator(int index)
- {
- return new SeqPosition<E,AbstractSequence<E>>(this, index, false);
- }
- public SeqPosition<E, AbstractSequence<E>> getIteratorAtPos(int ipos)
- {
- return new SeqPosition<E,AbstractSequence<E>>(this, copyPos(ipos));
- }
- public final Iterator<E> iterator()
- {
- return getIterator(0);
- }
- public final ListIterator<E> listIterator()
- {
- return getIterator(0);
- }
- public final ListIterator<E> listIterator(int index)
- {
- return getIterator(index);
- }
- /** Add a value at a specified Pos.
- * @return the updated Pos, which is after the inserted value..
- */
- protected int addPos (int ipos, E value)
- {
- throw unsupported("addPos");
- }
- /** See java.util.Collection. */
- public boolean add(E o)
- {
- addPos(endPos(), o);
- return true;
- }
- /** See java.util.List. */
- public void add(int index, E o)
- {
- int pos = createPos(index, false);
- addPos(pos, o);
- releasePos(pos);
- }
- /** See java.util.Collection. */
- public boolean addAll(Collection<? extends E> c)
- {
- return addAll(size(), c);
- }
- /** See java.util.Collection. */
- public boolean addAll(int index, Collection<? extends E> c)
- {
- boolean changed = false;
- int pos = createPos(index, false);
- for (Iterator<? extends E> it = c.iterator(); it.hasNext(); )
- {
- pos = addPos(pos, it.next());
- changed = true;
- }
- releasePos(pos);
- return changed;
- }
- /**
- * Remove one or more elements.
- * @param ipos position where elements should be removed
- * @param count if non-negative, remove that number of elements
- * following (poses, posNumber); if negative the negative of the number
- * of elements to remove before (poses, posNumber).
- * @exception java.lang.IndexOutOfBoundsException
- * if {@code (count >= 0 ? (index < 0 || index + count > size())
- * : (index + count < 0 || index > size()))},
- * where {@code index == nextIndex(ipos, xpos)}.
- */
- public void removePos(int ipos, int count)
- {
- int rpos = createRelativePos(ipos, count, false);
- if (count >= 0)
- removePosRange(ipos, rpos);
- else
- removePosRange(rpos, ipos);
- releasePos(rpos);
- }
- /** Remove a range where each end-point is a position in a container.
- * @param ipos0 start of range, as a poistion
- * @param ipos1 end of range
- * @exception java.lang.IndexOutOfBoundsException
- * if {@code nextIndex(ipos0) > nextIndex(ipos1)}
- * or {@code nextIndex(ipos0) < 0} or {@code nextIndex(ipos1) > size()}.
- */
- protected void removePosRange(int ipos0, int ipos1)
- {
- throw unsupported("removePosRange");
- }
- public E remove(int index)
- {
- if (index < 0 || index >= size())
- throw new IndexOutOfBoundsException();
- int ipos = createPos(index, false);
- E result = (E) getPosNext(ipos);
- removePos(ipos, 1);
- releasePos(ipos);
- return result;
- }
- public boolean remove(Object o)
- {
- int index = indexOf(o);
- if (index < 0)
- return false;
- int ipos = createPos(index, false);
- removePos(ipos, 1);
- releasePos(ipos);
- return true;
- }
- public boolean removeAll(Collection<?> c)
- {
- boolean changed = false;
- for (int iter = startPos(); (iter = nextPos(iter)) != 0; )
- {
- Object value = getPosPrevious(iter);
- if (c.contains(value))
- {
- removePos(iter, -1);
- changed = true;
- }
- }
- return changed;
- }
- public boolean retainAll(Collection<?> c)
- {
- boolean changed = false;
- for (int iter = startPos(); (iter = nextPos(iter)) != 0; )
- {
- Object value = getPosPrevious(iter);
- if (! c.contains(value))
- {
- removePos(iter, -1);
- changed = true;
- }
- }
- return changed;
- }
- public void clear()
- {
- removePos(startPos(), endPos());
- }
- /** Tests whether the position has the "isAfter" property.
- * I.e. if something is inserted at the position, will
- * the iterator end up being after the new data? */
- protected boolean isAfterPos (int ipos)
- {
- return (ipos & 1) != 0;
- }
- /** Generate a position at a given index.
- * The result is a position cookie that must be free'd with releasePos.
- * @param index offset from beginning of desired position
- * @param isAfter should the position have the isAfter property
- * @exception IndexOutOfBoundsException if index is out of bounds
- */
- public int createPos (int index, boolean isAfter) {
- return (index << 1) | (isAfter ? 1 : 0);
- }
- public int createRelativePos(int pos, int delta, boolean isAfter)
- {
- return createPos(nextIndex(pos) + delta, isAfter);
- }
- public int startPos () { return 0; }
- public int endPos () { return -1; }
- /**
- * Reclaim any resources used by the given position int.
- * @param ipos the Pos being free'd.
- */
- protected void releasePos(int ipos)
- {
- }
- /** Make a copy of a position int.
- * For simple positions returns the argument.
- * However, if the positions are magic cookies that are actively managed
- * by the sequence (as opposed to for example a simple index), then making
- * a copy may need to increment a reference count, or maybe allocate a
- * new position cookie. In any case, the new position is initialized to
- * the same offset (and isAfter property) as the original.
- * @param ipos the position being copied.
- * @return the new position
- */
- public int copyPos (int ipos)
- {
- return ipos;
- }
- /** Get offset of (ipos1) relative to (ipos0). */
- protected int getIndexDifference(int ipos1, int ipos0)
- {
- return nextIndex(ipos1) - nextIndex(ipos0);
- }
- /**
- * Get the offset from the beginning corresponding to a position cookie.
- */
- protected int nextIndex(int ipos) {
- return ipos == -1 ? size() : ipos >>> 1;
- }
- protected int fromEndIndex(int ipos)
- {
- return size() - nextIndex(ipos);
- }
- /**
- * Get the size of the (sub-) sequence containing a given position.
- * Normally the same as size(), but may be different if this Sequence
- * is a tree and the position points at an interior node.
- */
- protected int getContainingSequenceSize(int ipos)
- {
- return size();
- }
- public boolean hasNext (int ipos)
- {
- return nextIndex(ipos) != size();
- }
- public int getNextKind(int ipos)
- {
- return hasNext(ipos) ? Sequence.OBJECT_VALUE : Sequence.EOF_VALUE;
- }
- public String getNextTypeName(int ipos)
- {
- Object type = getNextTypeObject(ipos);
- return type == null ? null : type.toString();
- }
- public E getNextTypeObject(int ipos)
- {
- return null;
- }
- /** Called by SeqPosition.hasPrevious. */
- protected boolean hasPrevious(int ipos)
- {
- return nextIndex(ipos) != 0;
- }
- /** Return the next position following the argument.
- * The new position has the isAfter property.
- * The argument is implicitly released (as in releasePos).
- * Returns 0 if we are already at end of file.
- */
- public int nextPos (int ipos)
- {
- if (! hasNext(ipos))
- return 0;
- int next = createRelativePos(ipos, 1, true);
- releasePos(ipos);
- return next;
- }
- /** Return the previous position following the argument.
- * The new position has the isBefore property.
- * The argument is implicitly released (as in releasePos).
- * Returns -1 if we are already at beginning of file.
- */
- public int previousPos (int ipos)
- {
- if (! hasPrevious(ipos))
- return 0;
- int next = createRelativePos(ipos, -1, false);
- releasePos(ipos);
- return next;
- }
- /** 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 final boolean gotoChildrenStart(TreePosition pos)
- {
- int ipos = firstChildPos(pos.getPos());
- if (ipos == 0)
- return false;
- pos.push(this, ipos);
- return true;
- }
- /** Get position before first child (of the element following position).
- * @param ipos parent position. It is not released by this method.
- * @return non-zero position cookie if there is a child sequence
- * (which might be empty); zero if current position is end of sequence
- * or following element is atomic (cannot have children).
- */
- public int firstChildPos (int ipos)
- {
- return 0;
- }
- public int firstChildPos (int ipos, ItemPredicate predicate)
- {
- int child = firstChildPos(ipos);
- if (child == 0)
- return 0;
- if (predicate.isInstancePos(this, child))
- return child;
- else
- return nextMatching(child, predicate, endPos(), false);
- }
- /** Like firstChildPos.
- * Problem: Should this stop before we get to children?
- * I think so, but that requires changes to TreeList. */
- public int firstAttributePos (int ipos)
- {
- return 0;
- }
- /** Get position of parent.
- * @param ipos child position. It is not released by this method.
- * @return the p os of the parent, or endPos() is there is no known parent.
- */
- public int parentPos (int ipos)
- {
- return endPos();
- }
- protected boolean gotoParent(TreePosition pos)
- {
- if (pos.depth < 0)
- return false;
- pos.pop();
- return true;
- }
- public int getAttributeLength()
- {
- return 0;
- }
- public Object getAttribute(int index)
- {
- return null;
- }
- protected boolean gotoAttributesStart(TreePosition pos)
- {
- return false;
- }
- /** Get the element following the specified position.
- * @param ipos the specified position.
- * @return the following element, or eofValue if there is none.
- * Called by SeqPosition.getNext.
- * FIXME Should change eof handling so return type can be E.
- */
- public Object getPosNext(int ipos)
- {
- if (! hasNext(ipos))
- return Sequence.eofValue;
- return get(nextIndex(ipos));
- }
- /** Get the element before the specified position.
- * @param ipos the specified position.
- * @return the following element, or eofValue if there is none.
- * FIXME Should change eof handling so return type can be E.
- */
- public Object getPosPrevious(int ipos)
- {
- int index = nextIndex(ipos);
- if (index <= 0)
- return Sequence.eofValue;
- return get(index - 1);
- }
- protected void setPosNext(int ipos, E value)
- {
- int index = nextIndex(ipos);
- if (index >= size())
- throw new IndexOutOfBoundsException();
- set(index, value);
- }
- protected void setPosPrevious(int ipos, E value)
- {
- int index = nextIndex(ipos);
- if (index == 0)
- throw new IndexOutOfBoundsException();
- set(index - 1, value);
- }
- public final int nextIndex(SeqPosition pos)
- {
- return nextIndex(pos.ipos);
- }
- /** Compare two positions, and indicate if they are the same position. */
- public boolean equals(int ipos1, int ipos2)
- {
- return compare(ipos1, ipos2) == 0;
- }
- /** Compare two positions, and indicate their relative order. */
- public int compare(int ipos1, int ipos2)
- {
- int i1 = nextIndex(ipos1);
- int i2 = nextIndex(ipos2);
- return i1 < i2 ? -1 : i1 > i2 ? 1 : 0;
- }
- public final int compare(SeqPosition i1, SeqPosition i2)
- {
- return compare(i1.ipos, i2.ipos);
- }
- public Object[] toArray()
- {
- int len = size();
- Object[] arr = new Object[len];
- int it = startPos();
- int i = 0;
- while ((it = nextPos(it)) != 0)
- arr[i++] = getPosPrevious(it);
- return arr;
- }
- public <T> T[] toArray(T[] arr)
- {
- int alen = arr.length;
- int len = size();
- if (len > alen)
- {
- Class componentType = arr.getClass().getComponentType();
- arr = (T[]) java.lang.reflect.Array.newInstance(componentType, len);
- alen = len;
- }
-
- int it = startPos();
- for (int i = 0; (it = nextPos(it)) != 0; i++)
- {
- arr[i] = (T) getPosPrevious(it);
- }
- if (len < alen)
- arr[len] = null;
- return arr;
- }
- /** This is used for the XML concept of "document order". */
- public int stableCompare (AbstractSequence other)
- {
- int id1 = System.identityHashCode(this);
- int id2 = System.identityHashCode(other);
- return id1 < id2 ? -1 : id1 > id2 ? 1 : 0;
- }
- /** This is used for the XML concept of "document order".
- * It is overridden in gnu.xml.NodeTree for a more robust implementation.
- */
- public static int compare(AbstractSequence seq1, int pos1,
- AbstractSequence seq2, int pos2)
- {
- if (seq1 == seq2)
- return seq1.compare(pos1, pos2);
- return seq1.stableCompare(seq2);
- }
- public int hashCode()
- {
- if (rank() != 1 && this instanceof Array)
- return Arrays.hashCode((Array) this);
- // Implementation specified by the Collections specification.
- int hash = 1;
- for (int i = startPos(); (i = nextPos(i)) != 0; )
- {
- Object obj = getPosPrevious(i);
- hash = 31*hash + (obj==null ? 0 : obj.hashCode());
- }
- return hash;
- }
- public int boundedHash(int seed, int limit) {
- int count = 0;
- int sublimit = limit >> 1;
- for (int i = startPos(); (i = nextPos(i)) != 0; ) {
- if (++count > limit)
- break;
- int h = HashUtils.boundedHash(getPosPrevious(i), 0, sublimit);
- seed = HashUtils.murmur3step(seed, h);
- }
- return HashUtils.murmur3finish(seed, count);
- }
- public boolean equals(Object o)
- {
- // Compatible with the Collections specification.
- // FIXME should also depend on class?
- if (! (this instanceof java.util.List)
- || ! (o instanceof java.util.List))
- return this == o;
- Iterator<E> it1 = iterator();
- Iterator<E> it2 = ((java.util.List<E>) o).iterator();
- for (;;)
- {
- boolean more1 = it1.hasNext();
- boolean more2 = it2.hasNext();
- if (more1 != more2)
- return false;
- if (! more1)
- return true;
- E e1 = it1.next();
- E e2 = it2.next();
- if (e1 == null)
- {
- if (e2 != null)
- return false;
- }
- else if (! e1.equals(e2))
- return false;
- }
- }
- public Sequence subSequence(SeqPosition start, SeqPosition end)
- {
- return subSequencePos(start.ipos, end.ipos);
- }
- protected Sequence<E> subSequencePos(int ipos0, int ipos1)
- {
- return new SubSequence<E>(this, ipos0, ipos1);
- }
- public List<E> subList(int fromIx, int toIx)
- {
- return subSequencePos(createPos(fromIx, false),
- createPos(toIx, true));
- }
- /** Copy an element specified by a position pair to a Consumer.
- * @return if hasNext(ipos). */
- public boolean consumeNext (int ipos, Consumer out)
- {
- int next = nextPos(ipos);
- if (next == 0)
- return false;
- consumePosRange(ipos, next, out);
- return true;
- }
- public void consumePosRange(int iposStart, int iposEnd, Consumer out)
- {
- if (out.ignoring())
- return;
- int it = copyPos(iposStart);
- while (! equals(it, iposEnd))
- {
- if (! hasNext(it))
- throw new RuntimeException();
- out.writeObject(getPosNext(it));
- it = nextPos(it);
- }
- releasePos(it);
- }
-
- public void consume(int fromIndex, int toIndex, Consumer out) {
- int ipos0 = createPos(fromIndex, false);
- int ipos1 = createPos(toIndex, true);
- consumePosRange(ipos0, ipos1, out);
- releasePos(ipos0);
- releasePos(ipos1);
- }
- public void consume(Consumer out) {
- boolean isSequence =
- this instanceof Sequence && ! (this instanceof CharSequence);
- if (isSequence)
- out.startElement("#sequence");
- consumePosRange(startPos(), endPos(), out);
- if (isSequence)
- out.endElement();
- }
- public void toString (String sep, StringBuffer sbuf)
- {
- boolean seen = false;
- for (int i = startPos(); (i = nextPos(i)) != 0; )
- {
- if (seen)
- sbuf.append(sep);
- else
- seen = true;
- sbuf.append(getPosPrevious(i));
- }
- }
- public String toString ()
- {
- StringBuffer sbuf = new StringBuffer(100);
- if (this instanceof Sequence)
- sbuf.append('[');
- toString(", ", sbuf);
- if (this instanceof Sequence)
- sbuf.append(']');
- return sbuf.toString();
- }
- }
|