001/*
002 * Copyright (C) 2002-2015 Sebastiano Vigna
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *     http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016package regexodus.ds;
017
018import java.util.Arrays;
019import java.util.Collection;
020import java.util.Iterator;
021import java.util.List;
022import java.util.ListIterator;
023import java.util.NoSuchElementException;
024import java.util.RandomAccess;
025
026/**
027 * A type-specific array-based list; provides some additional methods that use polymorphism to avoid (un)boxing.
028 * <p>
029 * <P>This class implements a lightweight, fast, open, optimized, reuse-oriented version of array-based lists. Instances of this class represent a list with an array that is enlarged as needed when
030 * new entries are created (by doubling its current length), but is <em>never</em> made smaller (even on a {@link #clear()}). A family of {@linkplain #trim() trimming methods} lets you control the size
031 * of the backing array; this is particularly useful if you reuse instances of this class. Range checks are equivalent to those of {@link java.util}'s classes, but they are delayed as much as
032 * possible. The backing array is exposed by the {@link #elements()} method.
033 * <p>
034 * <p>This class implements the bulk methods <code>removeElements()</code>, <code>addElements()</code> and <code>getElements()</code> using high-performance system calls (e.g.,
035 * {@link System#arraycopy(Object, int, Object, int, int) System.arraycopy()} instead of expensive loops.
036 *
037 * @see java.util.ArrayList
038 */
039public class CharArrayList implements RandomAccess, Cloneable, java.io.Serializable, List<Character>, Comparable<List<? extends Character>> {
040    private static final long serialVersionUID = -7046029254386353130L;
041    /**
042     * The initial default capacity of an array list.
043     */
044    private final static int DEFAULT_INITIAL_CAPACITY = 16;
045    /**
046     * The backing array.
047     */
048    private transient char[] a;
049    /**
050     * The current actual size of the list (never greater than the backing-array length).
051     */
052    private int size;
053    //private static final boolean ASSERTS = false;
054
055    /**
056     * Creates a new array list using a given array.
057     * <p>
058     * <P>This constructor is only meant to be used by the wrapping methods.
059     *
060     * @param a the array that will be used to back this array list.
061     */
062    protected CharArrayList(final char a[], boolean dummy) {
063        this.a = a;
064    }
065
066    /**
067     * Creates a new array list with given capacity.
068     *
069     * @param capacity the initial capacity of the array list (may be 0).
070     */
071
072    public CharArrayList(final int capacity) {
073        if (capacity < 0) throw new IllegalArgumentException("Initial capacity (" + capacity + ") is negative");
074        a = new char[capacity];
075    }
076
077    /**
078     * Creates a new array list with {@link #DEFAULT_INITIAL_CAPACITY} capacity.
079     */
080    private CharArrayList() {
081        this(DEFAULT_INITIAL_CAPACITY);
082    }
083
084    /**
085     * Creates a new array list and fills it with a given type-specific list.
086     *
087     * @param l a type-specific list that will be used to fill the array list.
088     */
089    public CharArrayList(final CharArrayList l) {
090        this(l.size());
091        l.getElements(0, a, 0, size = l.size());
092    }
093
094    /**
095     * Creates a new array list and fills it with the elements of a given array or vararg.
096     *
097     * @param a an array or vararg whose elements will be used to fill the array list.
098     */
099    private CharArrayList(final char... a) {
100        this(a, 0, a.length);
101    }
102
103    /**
104     * Creates a new array list and fills it with the elements of a given String.
105     *
106     * @param s a String whose char elements will be used to fill the array list.
107     */
108    public CharArrayList(final String s) { this(s.toCharArray());}
109    /**
110     * Creates a new array list and fills it with the elements of a given array.
111     *
112     * @param a      an array whose elements will be used to fill the array list.
113     * @param offset the first element to use.
114     * @param length the number of elements to use.
115     */
116    private CharArrayList(final char a[], final int offset, final int length) {
117        this(length);
118        System.arraycopy(a, offset, this.a, 0, length);
119        size = length;
120    }
121
122    /**
123     * Creates a new array list and fills it with the elements returned by an iterator..
124     *
125     * @param i an iterator whose returned elements will fill the array list.
126     */
127    public CharArrayList(final Iterator<? extends Character> i) {
128        this();
129        while (i.hasNext())
130            this.add(i.next());
131    }
132
133    /**
134     * Returns the backing array of this list.
135     *
136     * @return the backing array.
137     */
138    public char[] elements() {
139        return a;
140    }
141
142    /**
143     * Wraps a given array into an array list of given size.
144     * <p>
145     * <P>Note it is guaranteed that the type of the array returned by {@link #elements()} will be the same (see the comments in the class documentation).
146     *
147     * @param a      an array to wrap.
148     * @param length the length of the resulting array list.
149     * @return a new array list of the given size, wrapping the given array.
150     */
151    private static CharArrayList wrap(final char a[], final int length) {
152        if (length > a.length)
153            throw new IllegalArgumentException("The specified length (" + length + ") is greater than the array size (" + a.length + ")");
154        final CharArrayList l = new CharArrayList(a, false);
155        l.size = length;
156        return l;
157    }
158
159    /**
160     * Wraps a given array into an array list.
161     * <p>
162     * <P>Note it is guaranteed that the type of the array returned by {@link #elements()} will be the same (see the comments in the class documentation).
163     *
164     * @param a an array to wrap.
165     * @return a new array list wrapping the given array.
166     */
167    public static CharArrayList wrap(final char a[]) {
168        return wrap(a, a.length);
169    }
170
171    /**
172     * Ensures that this array list can contain the given number of entries without resizing.
173     *
174     * @param capacity the new minimum capacity for this array list.
175     */
176
177    private void ensureCapacity(final int capacity) {
178        a = CharArrays.ensureCapacity(a, capacity, size);
179        //if (ASSERTS) assert size <= a.length;
180    }
181
182    /**
183     * Grows this array list, ensuring that it can contain the given number of entries without resizing, and in case enlarging it at least by a factor of two.
184     *
185     * @param capacity the new minimum capacity for this array list.
186     */
187
188    private void grow(final int capacity) {
189        a = CharArrays.grow(a, capacity, size);
190        //if (ASSERTS) assert size <= a.length;
191    }
192
193    private void add(final int index, final char k) {
194        ensureIndex(index);
195        grow(size + 1);
196        if (index != size) System.arraycopy(a, index, a, index + 1, size - index);
197        a[index] = k;
198        size++;
199        //if (ASSERTS) assert size <= a.length;
200    }
201
202    private boolean add(final char k) {
203        grow(size + 1);
204        a[size++] = k;
205        //if (ASSERTS) assert size <= a.length;
206        return true;
207    }
208    public boolean add(final int k) {
209        grow(size + 1);
210        a[size++] = (char)k;
211        //if (ASSERTS) assert size <= a.length;
212        return true;
213    }
214
215    public char getChar(final int index) {
216        if (index >= size)
217            throw new IndexOutOfBoundsException("Index (" + index + ") is greater than or equal to list size (" + size + ")");
218        return a[index];
219    }
220
221    public int getCodePoint(final int index) {
222        if (index >= size)
223            throw new IndexOutOfBoundsException("Index (" + index + ") is greater than or equal to list size (" + size + ")");
224        return a[index];
225    }
226
227    private int indexOf(final char k) {
228        for (int i = 0; i < size; i++)
229            if (((k) == (a[i]))) return i;
230        return -1;
231    }
232
233    public int lastIndexOf(final char k) {
234        for (int i = size; i-- != 0; )
235            if (((k) == (a[i]))) return i;
236        return -1;
237    }
238
239    private char removeChar(final int index) {
240        if (index >= size)
241            throw new IndexOutOfBoundsException("Index (" + index + ") is greater than or equal to list size (" + size + ")");
242        final char old = a[index];
243        size--;
244        if (index != size) System.arraycopy(a, index + 1, a, index, size - index);
245        //if (ASSERTS) assert size <= a.length;
246        return old;
247    }
248
249    private boolean rem(final char k) {
250        int index = indexOf(k);
251        if (index == -1) return false;
252        removeChar(index);
253        //if (ASSERTS) assert size <= a.length;
254        return true;
255    }
256
257    /**
258     * Delegates to the corresponding type-specific method.
259     *
260     * @deprecated Please use the corresponding type-specific method instead.
261     */
262    @Deprecated
263    public Character set(final int index, final Character ok) {
264        return set(index, ok.charValue());
265    }
266
267    /**
268     * Inserts the specified element at the specified position in this list
269     * (optional operation).  Shifts the element currently at that position
270     * (if any) and any subsequent elements to the right (adds one to their
271     * indices).
272     *
273     * @param index   index at which the specified element is to be inserted
274     * @param element element to be inserted
275     * @throws UnsupportedOperationException if the <tt>add</tt> operation
276     *                                       is not supported by this list
277     * @throws ClassCastException            if the class of the specified element
278     *                                       prevents it from being added to this list
279     * @throws NullPointerException          if the specified element is null and
280     *                                       this list does not permit null elements
281     * @throws IllegalArgumentException      if some property of the specified
282     *                                       element prevents it from being added to this list
283     * @throws IndexOutOfBoundsException     if the index is out of range
284     *                                       (<tt>index &lt; 0 || index &gt; size()</tt>)
285     */
286    @Override
287    public void add(int index, Character element) {
288
289    }
290
291    /**
292     * Removes the element at the specified position in this list (optional
293     * operation).  Shifts any subsequent elements to the left (subtracts one
294     * from their indices).  Returns the element that was removed from the
295     * list.
296     *
297     * @param index the index of the element to be removed
298     * @return the element previously at the specified position
299     * @throws UnsupportedOperationException if the <tt>remove</tt> operation
300     *                                       is not supported by this list
301     * @throws IndexOutOfBoundsException     if the index is out of range
302     *                                       (<tt>index &lt; 0 || index &gt;= size()</tt>)
303     */
304    @Override
305    public Character remove(int index) {
306        return null;
307    }
308
309    /**
310     * Returns the index of the first occurrence of the specified element
311     * in this list, or -1 if this list does not contain the element.
312     * More formally, returns the lowest index <tt>i</tt> such that
313     * <tt>(o==null&nbsp;?&nbsp;get(i)==null&nbsp;:&nbsp;o.equals(get(i)))</tt>,
314     * or -1 if there is no such index.
315     *
316     * @param o element to search for
317     * @return the index of the first occurrence of the specified element in
318     * this list, or -1 if this list does not contain the element
319     * @throws ClassCastException   if the type of the specified element
320     *                              is incompatible with this list
321     *                              (<a href="Collection.html#optional-restrictions">optional</a>)
322     * @throws NullPointerException if the specified element is null and this
323     *                              list does not permit null elements
324     *                              (<a href="Collection.html#optional-restrictions">optional</a>)
325     */
326    @Override
327    public int indexOf(Object o) {
328        return 0;
329    }
330
331    /**
332     * Returns the index of the last occurrence of the specified element
333     * in this list, or -1 if this list does not contain the element.
334     * More formally, returns the highest index <tt>i</tt> such that
335     * <tt>(o==null&nbsp;?&nbsp;get(i)==null&nbsp;:&nbsp;o.equals(get(i)))</tt>,
336     * or -1 if there is no such index.
337     *
338     * @param o element to search for
339     * @return the index of the last occurrence of the specified element in
340     * this list, or -1 if this list does not contain the element
341     * @throws ClassCastException   if the type of the specified element
342     *                              is incompatible with this list
343     *                              (<a href="Collection.html#optional-restrictions">optional</a>)
344     * @throws NullPointerException if the specified element is null and this
345     *                              list does not permit null elements
346     *                              (<a href="Collection.html#optional-restrictions">optional</a>)
347     */
348    @Override
349    public int lastIndexOf(Object o) {
350        return 0;
351    }
352
353    private char set(final int index, final char k) {
354        if (index >= size)
355            throw new IndexOutOfBoundsException("Index (" + index + ") is greater than or equal to list size (" + size + ")");
356        char old = a[index];
357        a[index] = k;
358        return old;
359    }
360
361    public boolean addAll(int index, final Collection<? extends Character> c) {
362        ensureIndex(index);
363        int n = c.size();
364        if (n == 0) return false;
365        Iterator<? extends Character> i = c.iterator();
366        while (n-- != 0)
367            add(index++, i.next());
368        return true;
369    }
370
371    /**
372     * Removes from this list all of its elements that are contained in the
373     * specified collection (optional operation).
374     *
375     * @param c collection containing elements to be removed from this list
376     * @return <tt>true</tt> if this list changed as a result of the call
377     * @throws UnsupportedOperationException if the <tt>removeAll</tt> operation
378     *                                       is not supported by this list
379     * @throws ClassCastException            if the class of an element of this list
380     *                                       is incompatible with the specified collection
381     *                                       (<a href="Collection.html#optional-restrictions">optional</a>)
382     * @throws NullPointerException          if this list contains a null element and the
383     *                                       specified collection does not permit null elements
384     *                                       (<a href="Collection.html#optional-restrictions">optional</a>),
385     *                                       or if the specified collection is null
386     * @see #remove(Object)
387     * @see #contains(Object)
388     */
389    @Override
390    public boolean removeAll(Collection<?> c) {
391        return false;
392    }
393
394    /**
395     * Retains only the elements in this list that are contained in the
396     * specified collection (optional operation).  In other words, removes
397     * from this list all of its elements that are not contained in the
398     * specified collection.
399     *
400     * @param c collection containing elements to be retained in this list
401     * @return <tt>true</tt> if this list changed as a result of the call
402     * @throws UnsupportedOperationException if the <tt>retainAll</tt> operation
403     *                                       is not supported by this list
404     * @throws ClassCastException            if the class of an element of this list
405     *                                       is incompatible with the specified collection
406     *                                       (<a href="Collection.html#optional-restrictions">optional</a>)
407     * @throws NullPointerException          if this list contains a null element and the
408     *                                       specified collection does not permit null elements
409     *                                       (<a href="Collection.html#optional-restrictions">optional</a>),
410     *                                       or if the specified collection is null
411     * @see #remove(Object)
412     * @see #contains(Object)
413     */
414    @Override
415    public boolean retainAll(Collection<?> c) {
416        return false;
417    }
418
419    public void clear() {
420        size = 0;
421        //if (ASSERTS) assert size <= a.length;
422    }
423
424    public int size() {
425        return size;
426    }
427
428    public void size(final int size) {
429        if (size > a.length) ensureCapacity(size);
430        if (size > this.size) Arrays.fill(a, this.size, size, ((char) 0));
431        this.size = size;
432    }
433
434    public boolean isEmpty() {
435        return size == 0;
436    }
437
438    /**
439     * Trims this array list so that the capacity is equal to the size.
440     *
441     * @see java.util.ArrayList#trimToSize()
442     */
443    public void trim() {
444        trim(0);
445    }
446
447    /**
448     * Trims the backing array if it is too large.
449     * <p>
450     * If the current array length is smaller than or equal to <code>n</code>, this method does nothing. Otherwise, it trims the array length to the maximum between <code>n</code> and {@link #size()}.
451     * <p>
452     * <P>This method is useful when reusing lists. {@linkplain #clear() Clearing a list} leaves the array length untouched. If you are reusing a list many times, you can call this method with a
453     * typical size to avoid keeping around a very large array just because of a few large transient lists.
454     *
455     * @param n the threshold for the trimming.
456     */
457
458    private void trim(final int n) {
459        if (n >= a.length || size == a.length) return;
460        final char t[] = new char[Math.max(n, size)];
461        System.arraycopy(a, 0, t, 0, size);
462        a = t;
463        //if (ASSERTS) assert size <= a.length;
464    }
465
466    /**
467     * Copies element of this type-specific list into the given array using optimized system calls.
468     *
469     * @param from   the start index (inclusive).
470     * @param a      the destination array.
471     * @param offset the offset into the destination array where to store the first element copied.
472     * @param length the number of elements to be copied.
473     */
474    private void getElements(final int from, final char[] a, final int offset, final int length) {
475        CharArrays.ensureOffsetLength(a, offset, length);
476        System.arraycopy(this.a, from, a, offset, length);
477    }
478
479
480    /**
481     * Removes elements of this type-specific list using optimized system calls.
482     *
483     * @param from the start index (inclusive).
484     * @param to   the end index (exclusive).
485     */
486    public void removeElements(final int from, final int to) {
487        CharArrays.ensureFromTo(size, from, to);
488        System.arraycopy(a, to, a, from, size - to);
489        size -= (to - from);
490    }
491
492    /**
493     * Adds elements to this type-specific list using optimized system calls.
494     *
495     * @param index  the index at which to add elements.
496     * @param a      the array containing the elements.
497     * @param offset the offset of the first element to add.
498     * @param length the number of elements to add.
499     */
500    public void addElements(final int index, final char a[], final int offset, final int length) {
501        ensureIndex(index);
502        CharArrays.ensureOffsetLength(a, offset, length);
503        grow(size + length);
504        System.arraycopy(this.a, index, this.a, index + length, size - index);
505        System.arraycopy(a, offset, this.a, index, length);
506        size += length;
507    }
508
509    private char[] toCharArray(char a[]) {
510        if (a == null || a.length < size) a = new char[size];
511        System.arraycopy(this.a, 0, a, 0, size);
512        return a;
513    }
514
515    public boolean addAll(final int index, final CharArrayList l) {
516        ensureIndex(index);
517        final int n = l.size();
518        if (n == 0) return false;
519        grow(size + n);
520        if (index != size) System.arraycopy(a, index, a, index + n, size - index);
521        l.getElements(0, a, index, n);
522        size += n;
523        //if (ASSERTS) assert size <= a.length;
524        return true;
525    }
526
527    public class CharListIterator implements Iterator<Character>, ListIterator<Character> {
528
529        public CharListIterator(int idx) {
530            index = idx;
531        }
532
533        /**
534         * Delegates to the corresponding type-specific method.
535         */
536        public Character previous() {
537            return previousChar();
538        }
539
540        int index, pos = index, last = -1;
541
542        public boolean hasNext() {
543            return pos < size;
544        }
545
546        public boolean hasPrevious() {
547            return pos > 0;
548        }
549
550        public char nextChar() {
551            if (!hasNext()) throw new NoSuchElementException();
552            return a[last = pos++];
553        }
554
555        public char previousChar() {
556            if (!hasPrevious()) throw new NoSuchElementException();
557            return a[last = --pos];
558        }
559
560        public int nextIndex() {
561            return pos;
562        }
563
564        public int previousIndex() {
565            return pos - 1;
566        }
567
568        /**
569         * Delegates to the corresponding type-specific method.
570         */
571        public void set(Character ok) {
572            set(ok.charValue());
573        }
574
575        /**
576         * Delegates to the corresponding type-specific method.
577         */
578        public void add(Character ok) {
579            add(ok.charValue());
580        }
581
582        public void add(char k) {
583            if (last == -1) throw new IllegalStateException();
584            CharArrayList.this.add(pos++, k);
585            last = -1;
586        }
587
588
589        public void set(char k) {
590            if (last == -1) throw new IllegalStateException();
591            CharArrayList.this.set(last, k);
592        }
593
594        public void remove() {
595            if (last == -1) throw new IllegalStateException();
596            CharArrayList.this.removeChar(last);
597                /* If the last operation was a next(), we are removing an element *before* us, and we must decrease pos correspondingly. */
598            if (last < pos) pos--;
599            last = -1;
600        }
601
602        /**
603         * Delegates to the corresponding type-specific method.
604         *
605         * @deprecated Please use the corresponding type-specific method instead.
606         */
607        @Deprecated
608        public Character next() {
609            return nextChar();
610        }
611
612        /**
613         * This method just iterates the type-specific version of {@link #next()} for at most <code>n</code> times, stopping if {@link #hasNext()} becomes false.
614         */
615        public int skip(final int n) {
616            int i = n;
617            while (i-- != 0 && hasNext())
618                nextChar();
619            return n - i - 1;
620        }
621
622    }
623
624    public CharListIterator iterator() {
625        return listIterator();
626    }
627
628    public CharListIterator listIterator() {
629        return listIterator(0);
630    }
631
632    public CharListIterator listIterator(final int index) {
633        ensureIndex(index);
634        return new CharListIterator(index);
635    }
636
637    /**
638     * Returns a view of the portion of this list between the specified
639     * <tt>fromIndex</tt>, inclusive, and <tt>toIndex</tt>, exclusive.  (If
640     * <tt>fromIndex</tt> and <tt>toIndex</tt> are equal, the returned list is
641     * empty.)  The returned list is backed by this list, so non-structural
642     * changes in the returned list are reflected in this list, and vice-versa.
643     * The returned list supports all of the optional list operations supported
644     * by this list.<p>
645     * <p>
646     * This method eliminates the need for explicit range operations (of
647     * the sort that commonly exist for arrays).  Any operation that expects
648     * a list can be used as a range operation by passing a subList view
649     * instead of a whole list.  For example, the following idiom
650     * removes a range of elements from a list:
651     * <pre>{@code
652     *      list.subList(from, to).clear();
653     * }</pre>
654     * Similar idioms may be constructed for <tt>indexOf</tt> and
655     * <tt>lastIndexOf</tt>, and all of the algorithms in the
656     * <tt>Collections</tt> class can be applied to a subList.<p>
657     * <p>
658     * The semantics of the list returned by this method become undefined if
659     * the backing list (i.e., this list) is <i>structurally modified</i> in
660     * any way other than via the returned list.  (Structural modifications are
661     * those that change the size of this list, or otherwise perturb it in such
662     * a fashion that iterations in progress may yield incorrect results.)
663     *
664     * @param fromIndex low endpoint (inclusive) of the subList
665     * @param toIndex   high endpoint (exclusive) of the subList
666     * @return a view of the specified range within this list
667     * @throws IndexOutOfBoundsException for an illegal endpoint index value
668     *                                   (<tt>fromIndex &lt; 0 || toIndex &gt; size ||
669     *                                   fromIndex &gt; toIndex</tt>)
670     */
671    @Override
672    public List<Character> subList(int fromIndex, int toIndex) {
673        return new CharArrayList(a, fromIndex, toIndex - fromIndex);
674    }
675
676    public CharArrayList clone() {
677        CharArrayList c = new CharArrayList(size);
678        System.arraycopy(a, 0, c.a, 0, size);
679        c.size = size;
680        return c;
681    }
682
683    /**
684     * Compares this type-specific array list to another one.
685     * <p>
686     * <P>This method exists only for sake of efficiency. The implementation inherited from the abstract implementation would already work.
687     *
688     * @param l a type-specific array list.
689     * @return true if the argument contains the same elements of this type-specific array list.
690     */
691    public boolean equals(final CharArrayList l) {
692        if (l == this) return true;
693        int s = size();
694        if (s != l.size()) return false;
695        final char[] a1 = a;
696        final char[] a2 = l.a;
697        while (s-- != 0)
698            if (a1[s] != a2[s]) return false;
699        return true;
700    }
701
702    /**
703     * Compares this array list to another array list.
704     * <p>
705     * <P>This method exists only for sake of efficiency. The implementation inherited from the abstract implementation would already work.
706     *
707     * @param l an array list.
708     * @return a negative integer, zero, or a positive integer as this list is lexicographically less than, equal to, or greater than the argument.
709     */
710
711    public int compareTo(final CharArrayList l) {
712        final int s1 = size(), s2 = l.size();
713        final char a1[] = a, a2[] = l.a;
714        char e1, e2;
715        int r, i;
716        for (i = 0; i < s1 && i < s2; i++) {
717            e1 = a1[i];
718            e2 = a2[i];
719            if ((r = (e1 - e2)) != 0) return r;
720        }
721        return i < s2 ? -1 : (i < s1 ? 1 : 0);
722    }
723
724    /**
725     * Compares this list to another object. If the argument is a {@link java.util.List}, this method performs a lexicographical comparison; otherwise, it throws a <code>ClassCastException</code>.
726     *
727     * @param l a list.
728     * @return if the argument is a {@link java.util.List}, a negative integer, zero, or a positive integer as this list is lexicographically less than, equal to, or greater than the argument.
729     * @throws ClassCastException if the argument is not a list.
730     */
731
732    public int compareTo(final List<? extends Character> l) {
733        if (l == this) return 0;
734        if (l instanceof CharArrayList) {
735            final CharListIterator i1 = listIterator(), i2 = ((CharArrayList) l).listIterator();
736            int r;
737            char e1, e2;
738            while (i1.hasNext() && i2.hasNext()) {
739                e1 = i1.nextChar();
740                e2 = i2.nextChar();
741                if ((r = (e1 - e2)) != 0) return r;
742            }
743            return i2.hasNext() ? -1 : (i1.hasNext() ? 1 : 0);
744        }
745        ListIterator<? extends Character> i1 = listIterator(), i2 = l.listIterator();
746        int r;
747        while (i1.hasNext() && i2.hasNext()) {
748            if ((r = ((Comparable<? super Character>) i1.next()).compareTo(i2.next())) != 0) return r;
749        }
750        return i2.hasNext() ? -1 : (i1.hasNext() ? 1 : 0);
751    }
752
753    /**
754     * Returns the hash code for this list, which is identical to {@link java.util.List#hashCode()}.
755     *
756     * @return the hash code for this list.
757     */
758    public int hashCode() {
759        CharListIterator i = iterator();
760        int h = 1, s = size();
761        while (s-- != 0) {
762            char k = i.nextChar();
763            h = 31 * h + (k);
764        }
765        return h;
766    }
767
768
769    /**
770     * Delegates to the corresponding type-specific method.
771     *
772     * @deprecated Please use the corresponding type-specific method instead.
773     */
774    @Deprecated
775    public Character get(final int index) {
776        return getChar(index);
777    }
778
779
780    /**
781     * Ensures that the given index is non-negative and not greater than the list size.
782     *
783     * @param index an index.
784     * @throws IndexOutOfBoundsException if the given index is negative or greater than the list size.
785     */
786    private void ensureIndex(final int index) {
787        if (index < 0) throw new IndexOutOfBoundsException("Index (" + index + ") is negative");
788        if (index > size())
789            throw new IndexOutOfBoundsException("Index (" + index + ") is greater than list size (" + (size()) + ")");
790    }
791
792    /**
793     * Ensures that the given index is non-negative and smaller than the list size.
794     *
795     * @param index an index.
796     * @throws IndexOutOfBoundsException if the given index is negative or not smaller than the list size.
797     */
798    protected void ensureRestrictedIndex(final int index) {
799        if (index < 0) throw new IndexOutOfBoundsException("Index (" + index + ") is negative");
800        if (index >= size())
801            throw new IndexOutOfBoundsException("Index (" + index + ") is greater than or equal to list size (" + (size()) + ")");
802    }
803
804
805    private boolean contains(final char k) {
806        return indexOf(k) >= 0;
807    }
808
809    /**
810     * Delegates to the corresponding type-specific method.
811     */
812    public boolean contains(final Object o) {
813        return contains(((((Character) (o)).charValue())));
814    }
815
816
817    public Object[] toArray() {
818        final Object[] a = new Object[size()];
819        objectUnwrap(iterator(), a);
820        return a;
821    }
822
823    /**
824     * Returns an array containing all of the elements in this list in
825     * proper sequence (from first to last element); the runtime type of
826     * the returned array is that of the specified array.  If the list fits
827     * in the specified array, it is returned therein.  Otherwise, a new
828     * array is allocated with the runtime type of the specified array and
829     * the size of this list.
830     * <p>
831     * <p>If the list fits in the specified array with room to spare (i.e.,
832     * the array has more elements than the list), the element in the array
833     * immediately following the end of the list is set to <tt>null</tt>.
834     * (This is useful in determining the length of the list <i>only</i> if
835     * the caller knows that the list does not contain any null elements.)
836     * <p>
837     * <p>Like the {@link #toArray()} method, this method acts as bridge between
838     * array-based and collection-based APIs.  Further, this method allows
839     * precise control over the runtime type of the output array, and may,
840     * under certain circumstances, be used to save allocation costs.
841     * <p>
842     * <p>Suppose <tt>x</tt> is a list known to contain only strings.
843     * The following code can be used to dump the list into a newly
844     * allocated array of <tt>String</tt>:
845     * <p>
846     * <pre>{@code
847     *     String[] y = x.toArray(new String[0]);
848     * }</pre>
849     * <p>
850     * Note that <tt>toArray(new Object[0])</tt> is identical in function to
851     * <tt>toArray()</tt>.
852     *
853     * @param a the array into which the elements of this list are to
854     *          be stored, if it is big enough; otherwise, a new array of the
855     *          same runtime type is allocated for this purpose.
856     * @return an array containing the elements of this list
857     * @throws ArrayStoreException  if the runtime type of the specified array
858     *                              is not a supertype of the runtime type of every element in
859     *                              this list
860     * @throws NullPointerException if the specified array is null
861     */
862    @Override
863    @SuppressWarnings("unchecked")
864    public <T> T[] toArray(T[] a) {
865        Character[] b;
866        if (a.length < size()) b = new Character[size()];
867        else b = (Character[]) a;
868        objectUnwrap(iterator(), b);
869        return (T[]) b;
870
871    }
872
873    public Character[] toArray(Character[] a) {
874        if (a.length < size()) a = new Character[size()];
875        objectUnwrap(iterator(), a);
876        return a;
877    }
878
879
880    /**
881     * Delegates to the corresponding type-specific method.
882     */
883    public boolean add(final Character o) {
884        return add(o.charValue());
885    }
886
887
888    /**
889     * Delegates to the type-specific <code>rem()</code> method.
890     */
891    public boolean remove(Object ok) {
892        return rem((((Character) (ok))));
893    }
894
895
896    /**
897     * Checks whether this collection contains all elements from the given collection.
898     *
899     * @param c a collection.
900     * @return <code>true</code> if this collection contains all elements of the argument.
901     */
902    public boolean containsAll(Collection<?> c) {
903        int n = c.size();
904        final Iterator<?> i = c.iterator();
905        while (n-- != 0)
906            if (!contains(i.next())) return false;
907        return true;
908    }
909
910    /**
911     * Adds all elements of the given collection to this collection.
912     *
913     * @param c a collection.
914     * @return <code>true</code> if this collection changed as a result of the call.
915     */
916    public boolean addAll(Collection<? extends Character> c) {
917        boolean retVal = false;
918        final Iterator<? extends Character> i = c.iterator();
919        int n = c.size();
920        while (n-- != 0)
921            if (add(i.next())) retVal = true;
922        return retVal;
923    }
924
925
926    /**
927     * Unwraps an iterator into an array starting at a given offset for a given number of elements.
928     * <p>
929     * <P>This method iterates over the given type-specific iterator and stores the elements returned, up to a maximum of <code>length</code>, in the given array starting at <code>offset</code>. The
930     * number of actually unwrapped elements is returned (it may be less than <code>max</code> if the iterator emits less than <code>max</code> elements).
931     *
932     * @param i     a type-specific iterator.
933     * @param array an array to contain the output of the iterator.
934     * @return the number of elements unwrapped.
935     */
936    private static <K> int objectUnwrap(final Iterator<? extends K> i, final K array[]) {
937        int j = array.length, offset = 0;
938        while (j-- != 0 && i.hasNext())
939            array[offset++] = i.next();
940        return array.length - j - 1;
941    }
942
943
944    public char[] toArray(char a[]) {
945        return toCharArray(a);
946    }
947
948    public char[] toCharArray() {
949        return toCharArray(null);
950    }
951
952    @Override
953    public String toString() {
954        return new String(a, 0, size);
955    }
956
957    /**
958     * Unwraps an iterator into an array starting at a given offset for a given number of elements.
959     * <p>
960     * <P>This method iterates over the given type-specific iterator and stores the elements returned, up to a maximum of <code>length</code>, in the given array starting at <code>offset</code>. The
961     * number of actually unwrapped elements is returned (it may be less than <code>max</code> if the iterator emits less than <code>max</code> elements).
962     *
963     * @param i     a type-specific iterator.
964     * @param array an array to contain the output of the iterator.
965     * @return the number of elements unwrapped.
966     */
967    public static int unwrap(final CharListIterator i, final char array[]) {
968        int j = array.length, offset = 0;
969        while (j-- != 0 && i.hasNext())
970            array[offset++] = i.nextChar();
971        return array.length - j - 1;
972    }
973
974
975    private static class CharArrays    /** A static, final, empty array. */
976    {
977        public static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
978        public final static char[] EMPTY_ARRAY = {};
979
980
981        /**
982         * Ensures that an array can contain the given number of entries.
983         * <p>
984         * <P>If you cannot foresee whether this array will need again to be enlarged, you should probably use <code>grow()</code> instead.
985         *
986         * @param array  an array.
987         * @param length the new minimum length for this array.
988         * @return <code>array</code>, if it contains <code>length</code> entries or more; otherwise, an array with <code>length</code> entries whose first <code>array.length</code> entries are the same
989         * as those of <code>array</code>.
990         */
991        public static char[] ensureCapacity(final char[] array, final int length) {
992            if (length > array.length) {
993                final char t[] =
994                        new char[length];
995                System.arraycopy(array, 0, t, 0, array.length);
996                return t;
997            }
998            return array;
999        }
1000
1001        /**
1002         * Ensures that an array can contain the given number of entries, preserving just a part of the array.
1003         *
1004         * @param array    an array.
1005         * @param length   the new minimum length for this array.
1006         * @param preserve the number of elements of the array that must be preserved in case a new allocation is necessary.
1007         * @return <code>array</code>, if it can contain <code>length</code> entries or more; otherwise, an array with <code>length</code> entries whose first <code>preserve</code> entries are the same as
1008         * those of <code>array</code>.
1009         */
1010        public static char[] ensureCapacity(final char[] array, final int length, final int preserve) {
1011            if (length > array.length) {
1012                final char t[] =
1013                        new char[length];
1014                System.arraycopy(array, 0, t, 0, preserve);
1015                return t;
1016            }
1017            return array;
1018        }
1019
1020        /**
1021         * Grows the given array to the maximum between the given length and the current length multiplied by two, provided that the given length is larger than the current length.
1022         * <p>
1023         * <P>If you want complete control on the array growth, you should probably use <code>ensureCapacity()</code> instead.
1024         *
1025         * @param array  an array.
1026         * @param length the new minimum length for this array.
1027         * @return <code>array</code>, if it can contain <code>length</code> entries; otherwise, an array with max(<code>length</code>,<code>array.length</code>/&phi;) entries whose first
1028         * <code>array.length</code> entries are the same as those of <code>array</code>.
1029         */
1030        public static char[] grow(final char[] array, final int length) {
1031            if (length > array.length) {
1032                final int newLength = (int) Math.max(Math.min(2L * array.length, MAX_ARRAY_SIZE), length);
1033                final char t[] =
1034                        new char[newLength];
1035                System.arraycopy(array, 0, t, 0, array.length);
1036                return t;
1037            }
1038            return array;
1039        }
1040
1041        /**
1042         * Grows the given array to the maximum between the given length and the current length multiplied by two, provided that the given length is larger than the current length, preserving just a part
1043         * of the array.
1044         * <p>
1045         * <P>If you want complete control on the array growth, you should probably use <code>ensureCapacity()</code> instead.
1046         *
1047         * @param array    an array.
1048         * @param length   the new minimum length for this array.
1049         * @param preserve the number of elements of the array that must be preserved in case a new allocation is necessary.
1050         * @return <code>array</code>, if it can contain <code>length</code> entries; otherwise, an array with max(<code>length</code>,<code>array.length</code>/&phi;) entries whose first
1051         * <code>preserve</code> entries are the same as those of <code>array</code>.
1052         */
1053        public static char[] grow(final char[] array, final int length, final int preserve) {
1054            if (length > array.length) {
1055                final int newLength = (int) Math.max(Math.min(2L * array.length, MAX_ARRAY_SIZE), length);
1056                final char t[] =
1057                        new char[newLength];
1058                System.arraycopy(array, 0, t, 0, preserve);
1059                return t;
1060            }
1061            return array;
1062        }
1063
1064        /**
1065         * Trims the given array to the given length.
1066         *
1067         * @param array  an array.
1068         * @param length the new maximum length for the array.
1069         * @return <code>array</code>, if it contains <code>length</code> entries or less; otherwise, an array with <code>length</code> entries whose entries are the same as the first <code>length</code>
1070         * entries of <code>array</code>.
1071         */
1072        public static char[] trim(final char[] array, final int length) {
1073            if (length >= array.length) return array;
1074            final char t[] =
1075                    length == 0 ? EMPTY_ARRAY : new char[length];
1076            System.arraycopy(array, 0, t, 0, length);
1077            return t;
1078        }
1079
1080        /**
1081         * Sets the length of the given array.
1082         *
1083         * @param array  an array.
1084         * @param length the new length for the array.
1085         * @return <code>array</code>, if it contains exactly <code>length</code> entries; otherwise, if it contains <em>more</em> than <code>length</code> entries, an array with <code>length</code>
1086         * entries whose entries are the same as the first <code>length</code> entries of <code>array</code>; otherwise, an array with <code>length</code> entries whose first <code>array.length</code>
1087         * entries are the same as those of <code>array</code>.
1088         */
1089        public static char[] setLength(final char[] array, final int length) {
1090            if (length == array.length) return array;
1091            if (length < array.length) return trim(array, length);
1092            return ensureCapacity(array, length);
1093        }
1094
1095        /**
1096         * Returns a copy of a portion of an array.
1097         *
1098         * @param array  an array.
1099         * @param offset the first element to copy.
1100         * @param length the number of elements to copy.
1101         * @return a new array containing <code>length</code> elements of <code>array</code> starting at <code>offset</code>.
1102         */
1103        public static char[] copy(final char[] array, final int offset, final int length) {
1104            ensureOffsetLength(array, offset, length);
1105            final char[] a =
1106                    length == 0 ? EMPTY_ARRAY : new char[length];
1107            System.arraycopy(array, offset, a, 0, length);
1108            return a;
1109        }
1110
1111        /**
1112         * Returns a copy of an array.
1113         *
1114         * @param array an array.
1115         * @return a copy of <code>array</code>.
1116         */
1117        public static char[] copy(final char[] array) {
1118            char[] next = new char[array.length];
1119            System.arraycopy(array, 0, next, 0, array.length);
1120            return next;
1121        }
1122
1123        /**
1124         * Fills the given array with the given value.
1125         *
1126         * @param array an array.
1127         * @param value the new value for all elements of the array.
1128         * @deprecated Please use the corresponding {@link java.util.Arrays} method.
1129         */
1130        @Deprecated
1131        public static void fill(final char[] array, final char value) {
1132            int i = array.length;
1133            while (i-- != 0)
1134                array[i] = value;
1135        }
1136
1137        /**
1138         * Fills a portion of the given array with the given value.
1139         *
1140         * @param array an array.
1141         * @param from  the starting index of the portion to fill (inclusive).
1142         * @param to    the end index of the portion to fill (exclusive).
1143         * @param value the new value for all elements of the specified portion of the array.
1144         * @deprecated Please use the corresponding {@link java.util.Arrays} method.
1145         */
1146        @Deprecated
1147        public static void fill(final char[] array, final int from, int to, final char value) {
1148            ensureFromTo(array, from, to);
1149            if (from == 0) while (to-- != 0)
1150                array[to] = value;
1151            else for (int i = from; i < to; i++)
1152                array[i] = value;
1153        }
1154
1155        /**
1156         * Returns true if the two arrays are element-wise equal.
1157         *
1158         * @param a1 an array.
1159         * @param a2 another array.
1160         * @return true if the two arrays are of the same length, and their elements are equal.
1161         * @deprecated Please use the corresponding {@link java.util.Arrays} method, which is intrinsic in recent JVMs.
1162         */
1163        @Deprecated
1164        public static boolean equals(final char[] a1, final char a2[]) {
1165            int i = a1.length;
1166            if (i != a2.length) return false;
1167            while (i-- != 0)
1168                if (!((a1[i]) == (a2[i]))) return false;
1169            return true;
1170        }
1171
1172        /**
1173         * Ensures that a range given by its first (inclusive) and last (exclusive) elements fits an array.
1174         * <p>
1175         * <P>This method may be used whenever an array range check is needed.
1176         *
1177         * @param a    an array.
1178         * @param from a start index (inclusive).
1179         * @param to   an end index (exclusive).
1180         * @throws IllegalArgumentException       if <code>from</code> is greater than <code>to</code>.
1181         * @throws ArrayIndexOutOfBoundsException if <code>from</code> or <code>to</code> are greater than the array length or negative.
1182         */
1183        public static void ensureFromTo(final char[] a, final int from, final int to) {
1184            ensureFromTo(a.length, from, to);
1185        }
1186
1187        /**
1188         * Ensures that a range given by an offset and a length fits an array.
1189         * <p>
1190         * <P>This method may be used whenever an array range check is needed.
1191         *
1192         * @param a      an array.
1193         * @param offset a start index.
1194         * @param length a length (the number of elements in the range).
1195         * @throws IllegalArgumentException       if <code>length</code> is negative.
1196         * @throws ArrayIndexOutOfBoundsException if <code>offset</code> is negative or <code>offset</code>+<code>length</code> is greater than the array length.
1197         */
1198        public static void ensureOffsetLength(final char[] a, final int offset, final int length) {
1199            ensureOffsetLength(a.length, offset, length);
1200        }
1201
1202        /**
1203         * Ensures that two arrays are of the same length.
1204         *
1205         * @param a an array.
1206         * @param b another array.
1207         * @throws IllegalArgumentException if the two argument arrays are not of the same length.
1208         */
1209        public static void ensureSameLength(final char[] a, final char[] b) {
1210            if (a.length != b.length)
1211                throw new IllegalArgumentException("Array size mismatch: " + a.length + " != " + b.length);
1212        }
1213
1214        /**
1215         * Ensures that a range given by its first (inclusive) and last (exclusive) elements fits an array of given length.
1216         * <p>
1217         * <P>This method may be used whenever an array range check is needed.
1218         *
1219         * @param arrayLength an array length.
1220         * @param from        a start index (inclusive).
1221         * @param to          an end index (inclusive).
1222         * @throws IllegalArgumentException       if <code>from</code> is greater than <code>to</code>.
1223         * @throws ArrayIndexOutOfBoundsException if <code>from</code> or <code>to</code> are greater than <code>arrayLength</code> or negative.
1224         */
1225        public static void ensureFromTo(final int arrayLength, final int from, final int to) {
1226            if (from < 0) throw new ArrayIndexOutOfBoundsException("Start index (" + from + ") is negative");
1227            if (from > to)
1228                throw new IllegalArgumentException("Start index (" + from + ") is greater than end index (" + to + ")");
1229            if (to > arrayLength)
1230                throw new ArrayIndexOutOfBoundsException("End index (" + to + ") is greater than array length (" + arrayLength + ")");
1231        }
1232
1233
1234        /**
1235         * Ensures that a range given by an offset and a length fits an array of given length.
1236         * <p>
1237         * <P>This method may be used whenever an array range check is needed.
1238         *
1239         * @param arrayLength an array length.
1240         * @param offset      a start index for the fragment
1241         * @param length      a length (the number of elements in the fragment).
1242         * @throws IllegalArgumentException       if <code>length</code> is negative.
1243         * @throws ArrayIndexOutOfBoundsException if <code>offset</code> is negative or <code>offset</code>+<code>length</code> is greater than <code>arrayLength</code>.
1244         */
1245        public static void ensureOffsetLength(final int arrayLength, final int offset, final int length) {
1246            if (offset < 0) throw new ArrayIndexOutOfBoundsException("Offset (" + offset + ") is negative");
1247            if (length < 0) throw new IllegalArgumentException("Length (" + length + ") is negative");
1248            if (offset + length > arrayLength)
1249                throw new ArrayIndexOutOfBoundsException("Last index (" + (offset + length) + ") is greater than array length (" + arrayLength + ")");
1250        }
1251    }
1252}