package waymaker.gen; // Copyright © 2015 Michael Allan. Licence MIT. import java.lang.reflect.Array; import java.util.*; /** A thread restricted variant of {@linkplain java.util.concurrent.CopyOnWriteArrayList * CopyOnWriteArrayList} that is non-blocking. It retains the advantages of compactness and speed, * often being “more efficient than alternatives when traversal operations vastly outnumber mutations”. * Moreover {@linkplain #set(int,Object) set mutations} will not affect efficiency because this variant * copies the underlying array only for resize mutations: only {@linkplain #add(Object) add} and * {@linkplain #remove(Object) remove} are “implemented by making a fresh copy” of the array, not * {@linkplain #set(int,Object) set}. */ public abstract class CopyOnResizeArrayList implements List, RandomAccess { /** Sets the elements by setting the underlying array, which is thenceforth owned by this list. */ public void array( final E[] _array ) { array = _array; } private E[] array = emptyArray(); private E[] array( final int length ) { return length == 0? emptyArray(): newArray(length); } /** Returns a zero-length array of the correct element type. */ public abstract E[] emptyArray(); /** Constructs a array of the correct element type, and a length of 1 or longer. * * @param length The non-zero length of array to construct. */ public abstract E[] newArray( int length ); // - C o l l e c t i o n ---------------------------------------------------------------------------- /** {@inheritDoc}

This method merely calls {@linkplain #add(int,Object) add}(size, addendum) * and returns true.

*/ public boolean add( final E addendum ) { add( array.length, addendum ); return true; } /** {@inheritDoc}

This method merely calls and returns * {@linkplain #addAll(int,Collection) addAll}(size, addenda).

*/ public final boolean addAll( final Collection addenda ) { return addAll( array.length, addenda ); } public final void clear() { throw new UnsupportedOperationException( "Not yet coded" ); } public final boolean contains( final Object ob ) { return indexOf(ob) > 0; } public final boolean containsAll( Collection col ) { throw new UnsupportedOperationException( "Not yet coded" ); } public final boolean isEmpty() { return array.length == 0; } /** {@inheritDoc} * This method merely calls {@linkplain #listIterator(int) listIterator}(0). */ public final ListIterator iterator() { return listIterator( 0 ); } public final boolean remove( final Object o ) { final int e = indexOf( o ); if( e < 0 ) return false; remove( e ); return true; } public final boolean removeAll( Collection col ) { throw new UnsupportedOperationException( "Not yet coded" ); } public final boolean retainAll( Collection col ) { throw new UnsupportedOperationException( "Not yet coded" ); } public final int size() { return array.length; } public final Object[] toArray() { return array.clone(); } public final @SuppressWarnings("unchecked") T[] toArray( T[] _array ) { final int eN = array.length; final int _eN = _array.length; if( _eN > eN ) _array[eN] = null; // null terminate else if( _eN < eN ) _array = (T[])Array.newInstance( _array.getClass().getComponentType(), eN ); System.arraycopy( array, 0, _array, 0, eN ); return _array; } // - L i s t ---------------------------------------------------------------------------------------- public void add( final int e, final E addendum ) { grow( e, 1 ); array[e] = addendum; } public boolean addAll( int e, final Collection addenda ) { final int addendumCount = addenda.size(); if( addendumCount == 0 ) return false; grow( e, addendumCount ); // all at once for speed for( final E addendum: addenda ) array[e++] = addendum; return true; } public final E get( final int e ) { return array[e]; } public final int indexOf( final Object ob ) { if( ob == null ) { for( int e = 0; e < array.length; ++e ) if( array[e] == null ) return e; } else for( int e = 0; e < array.length; ++e ) if( ob.equals( array[e] )) return e; return -1; } public final int lastIndexOf( final Object ob ) { if( ob == null ) { for( int e = array.length - 1; e >=0; ++e ) if( array[e] == null ) return e; } else for( int e = array.length - 1; e >=0; ++e ) if( ob.equals( array[e] )) return e; return -1; } /** {@inheritDoc} * This method merely calls {@linkplain #listIterator(int) listIterator}(0). */ public final ListIterator listIterator() { return listIterator( 0 ); } /** {@inheritDoc}

The returned iterator is based on a snapshot reference to the backing array. * It is similar in behaviour to the snapshot iterator of CopyOnWriteArrayList, except that it may * see underlying {@linkplain #set(int,Object) set mutations}. The iterator itself has no mutation * methods in the current implementation, pending future need.

* * @see java.util.concurrent.CopyOnWriteArrayList#listIterator(int) */ public final ListIterator listIterator( final int e ) { return new IteratorOnArray<>( e, array ); } public final E remove( final int e ) { final int eN = array.length; // old final int _eN = eN - 1; // new final E[] _array = array( _eN ); if( e > 0 ) System.arraycopy( array, 0, _array, 0, e ); final E removal = array[e]; if( e < _eN ) System.arraycopy( array, e + 1, _array, e, _eN - e ); array = _array; return removal; } public E set( final int e, final E element ) { final E elementWas = array[e]; array[e] = element; return elementWas; } public final List subList( int eFirst, int eEndBound ) { throw new UnsupportedOperationException( "Not yet coded" ); } //// P r i v a t e ///////////////////////////////////////////////////////////////////////////////////// /** Extends the list by addedSize then shifts the elements beginning at index e to the new end, thus * introducing a gap of length addedSize at e. */ private void grow( final int e, final int addedSize ) { final int eN = array.length; // old final int _eN = eN + addedSize; // new final E[] _array = array( _eN ); if( e > 0 ) System.arraycopy( array, 0, _array, 0, e ); if( e < eN ) System.arraycopy( array, e, _array, e + addedSize, eN - e ); array = _array; } }