|
| 1 | +package com.compilerprogramming.ezlang.compiler; |
| 2 | + |
| 3 | +import java.lang.StringBuilder; |
| 4 | +import java.lang.reflect.Array; |
| 5 | +import java.util.*; |
| 6 | + |
| 7 | +// ArrayList with saner syntax |
| 8 | +public class Ary<E> extends AbstractList<E> implements List<E> { |
| 9 | + public E[] _es; |
| 10 | + public int _len; |
| 11 | + |
| 12 | + public Ary(E[] es) { this(es,es.length); } |
| 13 | + public Ary(E[] es, int len) { if( es.length==0 ) es=Arrays.copyOf(es,1); _es=es; _len=len; } |
| 14 | + @SuppressWarnings("unchecked") |
| 15 | + public Ary(Class<E> clazz) { this((E[]) Array.newInstance(clazz, 1),0); } |
| 16 | + |
| 17 | + /** @return list is empty */ |
| 18 | + public boolean isEmpty() { return _len==0; } |
| 19 | + /** @return active list length */ |
| 20 | + public int len() { return _len; } |
| 21 | + public int size() { return len(); } |
| 22 | + |
| 23 | + /** @param i element index |
| 24 | + * @return element being returned; throws if OOB |
| 25 | + * @exception AIOOBE if !(0 <= i < _len) |
| 26 | + */ |
| 27 | + public E get( int i ) { return at(i); } |
| 28 | + public E at( int i ) { |
| 29 | + range_check(i); |
| 30 | + return _es[i]; |
| 31 | + } |
| 32 | + public E atX( int i ) { |
| 33 | + if( i >= _len ) return null; |
| 34 | + return _es[i]; |
| 35 | + } |
| 36 | + |
| 37 | + /** @return last element */ |
| 38 | + public E last( ) { return at(_len-1); } |
| 39 | + |
| 40 | + /** Add element in amortized constant time |
| 41 | + * @param e Element to add at end of list |
| 42 | + **/ |
| 43 | + public E push( E e ) { |
| 44 | + if( _len >= _es.length ) _es = Arrays.copyOf(_es,Math.max(1,_es.length<<1)); |
| 45 | + return (_es[_len++] = e); |
| 46 | + } |
| 47 | + /** @return remove and return last element */ |
| 48 | + public E pop( ) { |
| 49 | + return _len==0 ? null : _es[--_len]; |
| 50 | + } |
| 51 | + @Override public E removeLast() { return pop(); } |
| 52 | + |
| 53 | + |
| 54 | + /** Add element in amortized constant time |
| 55 | + * @param e Element to add at end of list |
| 56 | + * @return true */ |
| 57 | + public boolean add( E e ) { |
| 58 | + if( _len >= _es.length ) _es = Arrays.copyOf(_es,Math.max(1,_es.length<<1)); |
| 59 | + _es[_len++] = e; |
| 60 | + return true; |
| 61 | + } |
| 62 | + |
| 63 | + /** Fast, constant-time, element removal. Does not preserve order |
| 64 | + * @param i element to be removed |
| 65 | + * @return element removed */ |
| 66 | + public E del( int i ) { |
| 67 | + range_check(i); |
| 68 | + E tmp = _es[i]; |
| 69 | + _es[i]=_es[--_len]; |
| 70 | + return tmp; |
| 71 | + } |
| 72 | + |
| 73 | + /** Slow, linear-time, element removal. Preserves order. |
| 74 | + * @param i element to be removed |
| 75 | + * @return element removed */ |
| 76 | + @Override public E remove( int i ) { |
| 77 | + range_check(i); |
| 78 | + E e = _es[i]; |
| 79 | + System.arraycopy(_es,i+1,_es,i,(--_len)-i); |
| 80 | + return e; |
| 81 | + } |
| 82 | + |
| 83 | + /** Slow, linear-time, element insertion. Preserves order. |
| 84 | + * @param i where to insert |
| 85 | + * @return element inserted */ |
| 86 | + public E insert( E e, int i ) { |
| 87 | + setLen(_len+1); |
| 88 | + System.arraycopy(_es,i,_es,i+1,_len-i); |
| 89 | + _es[i] = e; |
| 90 | + return e; |
| 91 | + } |
| 92 | + |
| 93 | + |
| 94 | + /** Remove all elements */ |
| 95 | + public void clear( ) { _len=0; } |
| 96 | + |
| 97 | + /** Set existing element |
| 98 | + * @param i element to set |
| 99 | + * @param e value to set |
| 100 | + * @return old value |
| 101 | + * @exception AIOOBE if !(0 <= i < _len) |
| 102 | + */ |
| 103 | + public E set( int i, E e ) { |
| 104 | + range_check(i); |
| 105 | + E old = _es[i]; |
| 106 | + _es[i] = e; |
| 107 | + return old; |
| 108 | + } |
| 109 | + |
| 110 | + /** Set existing element |
| 111 | + * @param i element to set |
| 112 | + * @param e value to set |
| 113 | + * @return old value |
| 114 | + * @exception AIOOBE if !(0 <= i < _len) |
| 115 | + */ |
| 116 | + public E setX( int i, E e ) { |
| 117 | + if( i >= _len ) { |
| 118 | + while( i >= _es.length ) _es = Arrays.copyOf( _es, _es.length << 1 ); |
| 119 | + _len = i+1; |
| 120 | + } |
| 121 | + E old = _es[i]; |
| 122 | + _es[i] = e; |
| 123 | + return old; |
| 124 | + } |
| 125 | + |
| 126 | + public Ary<E> setLen( int len ) { |
| 127 | + if( len > _len ) |
| 128 | + while( len>= _es.length ) _es = Arrays.copyOf(_es,_es.length<<1); |
| 129 | + _len = len; |
| 130 | + while( _es.length > (len<<1) ) // Shrink if hugely too large |
| 131 | + _es = Arrays.copyOf(_es,_es.length>>1); |
| 132 | + Arrays.fill(_es,len,_es.length,null); |
| 133 | + return this; |
| 134 | + } |
| 135 | + |
| 136 | + public E swap( int i, int j ) { |
| 137 | + range_check(i); |
| 138 | + range_check(j); |
| 139 | + E tmp = _es[i]; |
| 140 | + if( i==j ) return tmp; |
| 141 | + _es[i] = _es[j]; |
| 142 | + _es[j] = tmp; |
| 143 | + return tmp; |
| 144 | + } |
| 145 | + |
| 146 | + |
| 147 | + /** @param c Collection to be added */ |
| 148 | + public boolean addAll( Collection<? extends E> c ) { |
| 149 | + if( c==null ) return false; |
| 150 | + for( E e : c ) add(e); |
| 151 | + return true; |
| 152 | + } |
| 153 | + public Ary<E> addAll( Iterable<? extends E> it ) { for( E e : it ) add(e); return this; } |
| 154 | + |
| 155 | + /** @param es Array to be added */ |
| 156 | + public <F extends E> Ary<E> addAll( F[] es ) { |
| 157 | + if( es==null || es.length==0 ) return this; |
| 158 | + while( _len+es.length > _es.length ) _es = Arrays.copyOf(_es,_es.length<<1); |
| 159 | + System.arraycopy(es,0,_es,_len,es.length); |
| 160 | + _len += es.length; |
| 161 | + return this; |
| 162 | + } |
| 163 | + |
| 164 | + /** @param c Collection to be added */ |
| 165 | + public Ary<E> addAll( Ary<? extends E> c ) { |
| 166 | + if( c==null || c._len==0 ) return this; |
| 167 | + while( _len+c._len > _es.length ) _es = Arrays.copyOf(_es,_es.length<<1); |
| 168 | + System.arraycopy(c._es,0,_es,_len,c._len); |
| 169 | + _len += c._len; |
| 170 | + return this; |
| 171 | + } |
| 172 | + |
| 173 | + /** @return compact array version */ |
| 174 | + public E[] asAry() { return Arrays.copyOf(_es,_len); } |
| 175 | + |
| 176 | + /** Find the first matching element using ==, or -1 if none. Note that |
| 177 | + * most del calls shuffle the list, so the first element might be random. |
| 178 | + * @param e Element to find |
| 179 | + * @return index of first matching element, or -1 if none */ |
| 180 | + public int find( E e ) { |
| 181 | + for( int i=0; i<_len; i++ ) if( _es[i]==e ) return i; |
| 182 | + return -1; |
| 183 | + } |
| 184 | + |
| 185 | + |
| 186 | + /** @return an iterator */ |
| 187 | + @Override public Iterator<E> iterator() { return new Iter(); } |
| 188 | + private class Iter implements Iterator<E> { |
| 189 | + int _i=0; |
| 190 | + @Override public boolean hasNext() { return _i<_len; } |
| 191 | + @Override public E next() { return _es[_i++]; } |
| 192 | + } |
| 193 | + |
| 194 | + @Override public String toString() { |
| 195 | + StringBuilder sb = new StringBuilder().append('{'); |
| 196 | + for( int i=0; i<_len; i++ ) { |
| 197 | + if( i>0 ) sb.append(','); |
| 198 | + if( _es[i] != null ) sb.append(_es[i].toString()); |
| 199 | + } |
| 200 | + return sb.append('}').toString(); |
| 201 | + } |
| 202 | + |
| 203 | + private void range_check( int i ) { |
| 204 | + if( i < 0 || i>=_len ) |
| 205 | + throw new ArrayIndexOutOfBoundsException(""+i+" >= "+_len); |
| 206 | + } |
| 207 | + |
| 208 | + // Note that the hashCode() and equals() are not invariant to changes in the |
| 209 | + // underlying array. If the hashCode() is used (e.g., inserting into a |
| 210 | + // HashMap) and the then the array changes, the hashCode() will change also. |
| 211 | + @Override public boolean equals( Object o ) { |
| 212 | + if( this==o ) return true; |
| 213 | + if( !(o instanceof Ary ary) ) return false; |
| 214 | + if( _len != ary._len ) return false; |
| 215 | + if( _es == ary._es ) return true; |
| 216 | + for( int i=0; i<_len; i++ ) |
| 217 | + if( !(_es[i]==null ? (ary._es[i] == null) : _es[i].equals(ary._es[i])) ) |
| 218 | + return false; |
| 219 | + return true; |
| 220 | + } |
| 221 | + @Override public int hashCode( ) { |
| 222 | + int sum=_len; |
| 223 | + for( int i=0; i<_len; i++ ) |
| 224 | + sum += _es[i]==null ? 0 : _es[i].hashCode(); |
| 225 | + return sum; |
| 226 | + } |
| 227 | + |
| 228 | +} |
0 commit comments