/* * `gnu.iou' * Copyright (C) 2006 John Pritchard. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * 02111-1307 USA */ package gnu.iou; import java.util.Enumeration; import java.util.NoSuchElementException; /** * A fast, recycling linked- list queue * * @author John Pritchard (john@syntelos.org) */ public class fq extends Object implements Enumeration, Cloneable { /** * List node. * * @author John Pritchard */ public static class fqn extends Object implements Cloneable { protected Object o = null; protected fqn n = null; public fqn(){ super(); } public Object get(){ return o; } public void free(){ o = null; n = null; } public void clear(){ if ( null != n) n.clear(); o = null; n = null; } public boolean contains( Object obj){ if ( obj.equals(this.o)) return true; else if ( null != n) return n.contains(obj); else return false; } public void reinit( Object obj){ o = obj; n = null; } public String toString(){ return super.toString()+"["+o+"]"; } public fqn clonefqn(){ try { fqn enq = (fqn)super.clone(); if ( this.o instanceof copy) enq.o = ((copy)this.o).copy(); if ( null != n) enq.n = this.n.clonefqn(); return enq; } catch ( CloneNotSupportedException cnx){ return null; } } /** * Clone, dropping without remainer of list */ public fqn copy(){ try { fqn enq = (fqn)super.clone(); if ( this.o instanceof copy) enq.o = ((copy)this.o).copy(); enq.n = null; return enq; } catch ( CloneNotSupportedException cnx){ return null; } } } ///////fq//// private volatile fqn list = null; /** * Recycle bin */ private fqn free_q = null; /** * Create a new FIFO queue */ public fq(){ super(); } public void clear(){ if ( null != list){ list.clear(); list = null; } if ( null != free_q){ free_q.clear(); free_q = null; } } public boolean contains ( Object obj){ if ( null == list || null == obj) return false; else return list.contains(obj); } /** * @param o Object to push (Push null produces pop null). */ public synchronized void push( Object o){ if ( null == list){ list = free_pop(o); return; } else { for ( fqn q = list; q != null; q = q.n){ if ( null == q.n){ q.n = free_pop(o); return; } } } } /** * Look at the next "pop" element without popping it (removing it) */ public Object peek(){ if ( null != list) return list.o; else return null; } /** * Return and remove the next element from the queue */ public synchronized Object pop(){ if ( null == list) return null; else { fqn q = this.list; Object ret = q.o; this.list = q.n; free_push(q); return ret; } } public boolean isEmpty(){ return (null == peek());} public boolean isNotEmpty(){ return (null != peek());} /** */ public int size(){ if ( null == list) return 0; else { int many = 0; for ( fqn q = list; null != q; q = q.n) many++; return many; } } /** * @param obj Non null target to remove, identity by object "equals" method. * @returns Enqueued object removed, or null for none. */ public Object remove ( Object obj){ if ( null == list || null == obj) return null; else { for ( fqn q = list, p = null; null != q; p = q, q = q.n){ if ( obj.equals(q.o)){ obj = q.o; if ( null == p) list = q.n; else p.n = q.n; free_push(q); return obj; } } return null; } } /** * @param obj Non null finder, identity by object "equals" method. * @returns Enqueued object, or null for none. */ public Object find ( Object obj){ if ( null == list || null == obj) return null; else { for ( fqn q = list, p = null; null != q; p = q, q = q.n){ if ( obj.equals(q.o)) return q.o; } return null; } } /** * Size greater than one. */ public boolean size_gt_1(){ return (null != list && null != list.n); } /** * Pop all elements into a string. Concatenate all enqueued * elements into a string, each separated by a space (0x20). */ public String popall_String(){ return popall_String(' '); } public String toString(){ chbuf strbuf = new chbuf(); strbuf.append("fq"); int many = 0; Object obj; for ( fqn q = list; null != q; q = q.n){ obj = q.o; if ( null != obj){ if ( 0 == many) strbuf.append('['); else strbuf.append(','); many += 1; strbuf.append(obj); } } if ( 0 < many) strbuf.append(']'); return strbuf.toString(); } public boolean equals ( Object ano){ if ( ano == this) return true; else if ( ano instanceof fq) return toString().equals(ano.toString()); else return false; } public fq cloneQueue(){ try { fq clone = (fq)super.clone(); if ( null != list) clone.list = list.clonefqn(); clone.free_q = null; return clone; } catch ( CloneNotSupportedException cnx){ return null; } } /** * Clone without depth of queue -- with only the top element of * the queue. */ public fq copy(){ try { fq clone = (fq)super.clone(); if ( null != list) clone.list = list.copy(); clone.free_q = null; return clone; } catch ( CloneNotSupportedException cnx){ return null; } } /** * Pop all elements into a string. Concatenate all enqueued * elements into a string, each separated by the argument * character. Uses the java Object 'toString' method. */ public String popall_String( char sep){ if (null == list) return null; chbuf strbuf = new chbuf(); Object o ; while ( null != (o = pop())){ strbuf.append(o); if ( null != list) strbuf.append(sep); } return strbuf.toString(); } private void free_push ( fqn eo){ eo.free(); if ( null == free_q) free_q = eo; else { eo.n = free_q; free_q = eo; } } private fqn free_pop ( Object o){ fqn f = free_q; if ( null == f){ f = new fqn(); f.reinit(o); return f; } else { free_q = f.n; f.reinit(o); return f; } } /** * Returns true if the enumeration contains more elements; false * if its empty. * * @see java.util.Enumeration */ public boolean hasMoreElements(){ return isEmpty(); } /** * Returns the next element of the enumeration. Calls to this * method will enumerate successive elements. * * @exception NoSuchElementException If no more elements exist. * * @see java.util.Enumeration */ public Object nextElement(){ if (isEmpty()) throw new NoSuchElementException(); else return pop(); } public Enumeration elements(){ return this.cloneQueue(); } }